
C언어 구조체 정렬과 padding을 이해할 때 가장 중요한 출발점은 이것입니다. 구조체는 필드를 종이 위에 순서대로 적어 놓은 목록이 아니라, 메모리에서 읽기 좋은 위치에 맞춰 배치되는 자료형입니다.
sizeof(struct)은 필드 크기의 단순 합이 아니라, alignment와 padding까지 반영한 결과일 수 있습니다.

C언어 구조체 정렬과 padding에서 alignment는 무엇인가
alignment는 어떤 타입이 메모리에서 보통 몇 바이트 경계에 놓이기를 기대하는가에 관한 개념입니다. 예를 들어 어떤 환경에서는 int가 4바이트 경계에 놓이면 CPU가 더 자연스럽게 읽을 수 있습니다.
입문 단계에서는 정렬은 성능과 접근 편의 때문에 생기는 메모리 배치 규칙이라고 이해하면 충분합니다. 이 규칙을 맞추기 위해 컴파일러가 중간에 빈칸을 넣을 수 있는데, 그 빈칸이 padding입니다.
padding은 왜 생길까
구조체 안에 크기가 다른 필드가 섞여 있으면, 다음 필드가 원하는 정렬 위치에 오도록 중간에 몇 바이트를 비워 둘 수 있습니다. 즉 padding은 낭비를 위한 공간이 아니라, 메모리 배치를 정렬 규칙에 맞추기 위한 완충 공간입니다.
- 중간 padding: 멤버와 멤버 사이에 끼어드는 빈칸
- tail padding: 구조체 맨 끝에 붙는 빈칸

가장 많이 보는 예시: 왜 5가 아니라 8이 될까
struct Example {
char a;
int b;
};이 구조체를 흔한 환경 기준으로 직관적으로 그려 보면 이렇게 볼 수 있습니다. a가 먼저 1바이트를 차지합니다. 그런데 그다음 b는 보통 4바이트 경계에 놓이기를 원할 수 있습니다. 그래서 a 다음에 3바이트 padding이 들어가고, 그 다음에 b가 4바이트를 차지합니다.
즉 1 + 3 + 4가 되어 총 8바이트가 됩니다. 그래서 단순 합 5와 실제 sizeof 8 사이에 차이가 생깁니다.

tail padding은 왜 마지막에도 붙을까
많이 놓치는 부분이 tail padding입니다. 구조체 하나만 볼 때는 마지막 빈칸이 불필요해 보일 수 있습니다. 하지만 구조체 배열을 생각하면 이유가 보입니다.
만약 구조체 크기가 정렬 단위에 맞지 않으면, 배열에서 다음 구조체가 시작하는 위치도 어긋날 수 있습니다. 그래서 컴파일러는 구조체 전체 크기에도 정렬을 맞추기 위해 마지막에 padding을 더할 수 있습니다.
tail padding은 다음 구조체 원소가 다시 올바른 정렬 위치에서 시작하게 만들기 위한 장치로 이해하면 좋습니다.
필드 순서를 바꾸면 왜 크기가 달라질 수 있을까
struct A {
char a;
int b;
char c;
};
struct B {
int b;
char a;
char c;
};이 두 구조체는 같은 멤버를 가지고 있어도 배치 순서가 다르기 때문에 padding의 양이 달라질 수 있습니다. 작은 타입과 큰 타입을 섞어 놓으면 중간 빈칸이 늘어나기 쉽고, 큰 타입을 먼저 모아 두면 padding이 줄어드는 경우가 많습니다.

물론 이것도 환경에 따라 결과가 달라질 수 있으니, 숫자 하나를 절대 규칙처럼 외우기보다 정렬 요구가 큰 타입이 중간에 오면 padding이 생기기 쉽다는 감각을 잡는 것이 더 중요합니다.
packed는 padding을 없애는 만능 해법일까
padding이 싫다고 해서 무조건 packed 속성이나 pragma를 쓰는 것은 조심해야 합니다. padding을 줄일 수는 있지만, 정렬이 맞지 않는 접근이 생기면 성능이 나빠지거나 이식성이 떨어질 수 있기 때문입니다.
- 메모리 공간은 줄어들 수 있다
- 하지만 CPU가 비정렬 접근을 싫어하는 환경에서는 비용이 생길 수 있다
- 바이너리 포맷, 네트워크 패킷, 하드웨어 레지스터처럼 정말 필요한 이유가 있을 때만 신중히 쓴다
즉 packed는 기본값을 무시하는 특별한 도구에 가깝습니다. 입문 단계에서는 먼저 일반적인 구조체 배치를 이해한 뒤, 왜 어떤 상황에서만 packed가 필요한지 보는 순서가 안전합니다.
입문자가 자주 하는 오해
- sizeof는 항상 필드 크기를 더한 값이라고 생각한다
- padding은 쓸모없는 낭비라고만 생각한다
- 구조체 끝에는 padding이 없을 것이라고 생각한다
- packed를 쓰면 무조건 더 좋은 것이라고 생각한다
padding은 구조체를 이해할 때 귀찮은 예외가 아니라, 오히려 메모리 배치를 이해하는 핵심 단서입니다. 이 감각이 잡히면 포인터 연산, 배열, 바이너리 파일 구조를 볼 때도 훨씬 덜 헷갈립니다.
마무리
- 구조체 크기는 필드 합만으로 결정되지 않을 수 있다
- alignment를 맞추기 위해 중간 padding이 생길 수 있다
- 배열 배치를 위해 tail padding도 붙을 수 있다
- 필드 순서를 바꾸면 sizeof가 달라질 수 있다
- packed는 이유가 분명할 때만 신중히 써야 한다
C 포인터와 메모리 감각을 더 함께 보고 싶다면 C언어 포인터 쉽게 이해하기, 선언 구조를 더 보고 싶다면 배열 포인터와 포인터 배열 차이도 이어서 읽어보면 좋습니다.
기본 개념은 cppreference의 object / alignment 설명, GNU C Structure Layout, GCC packed attribute 문서를 참고했습니다.