Quick Reference
구조체는 각 멤버의 정렬 조건 때문에 사이와 끝에 padding byte를 둘 수 있습니다. 내부 메모리 절약과 외부 ABI·파일 형식 호환성은 별개의 결정입니다.
| 필요한 일 | 선택 | 이유 |
|---|---|---|
| 필드 위치를 확인 | offsetof(Type, field) | 실제 layout을 확인합니다. |
| private 구조체 크기를 줄임 | 큰 정렬 멤버를 앞에 배치 | padding이 줄 수 있습니다. |
| 파일·네트워크 전송 | 필드 단위 encode | padding·endian·포인터를 피합니다. |
| packed layout 강제 | 플랫폼 전용 옵션 | unaligned access와 이식성을 검토합니다. |
struct Padded {
char a;
int b;
char c;
};문법
패딩은 컴파일러가 임의로 장난치는 공간이 아니라, CPU가 특정 타입을 더 정렬된 주소에서 읽기 쉽도록 넣는 빈칸입니다.
struct Bad {
char a;
int b;
char c;
};
struct Better {
int b;
char a;
char c;
};이 구조체는 멤버 크기만 더한 값처럼 보이지 않을 수 있습니다. 이유는 CPU가 특정 타입을 정렬된 주소에서 읽는 것을 선호하기 때문입니다.
그래서 컴파일러는 중간에 보이지 않는 패딩 바이트를 넣습니다.
즉 구조체를 설계할 때는 의미뿐 아니라 정렬 비용도 같이 보게 됩니다.
내부에서만 쓰는 큰 배열의 원소처럼 메모리가 중요한 구조체는 필드 순서를 조정할 수 있습니다. 반대로 공개 헤더·저장 형식·ABI에 노출된 구조체는 순서를 바꾸면 호환성이 깨질 수 있으므로, 크기 최적화보다 계약을 우선합니다.
정렬과 직렬화
size_t offset = offsetof(struct Padded, b);이 값으로 특정 필드가 실제로 어디에 놓였는지 알 수 있습니다. 바이너리 포맷이나 저수준 디버깅에서 특히 유용합니다.
자주 하는 오해
구조체를 메모리 그대로 파일이나 소켓에 써도 된다고 생각하는 것입니다.
- 패딩이 같이 들어갈 수 있다
- 플랫폼/컴파일러에 따라 배치가 달라질 수 있다
즉 구조체는 "그냥 직렬화 버퍼"가 아니라, 메모리 레이아웃이 구현 세부사항을 포함하는 타입입니다.
#pragma pack은 표준 C가 아니며, 강제로 좁은 정렬을 만들면 일부 환경에서 unaligned access 비용이나 오류가 생길 수 있습니다. 외부 형식은 정해진 폭의 필드를 byte order까지 변환해 읽고 쓰는 방식으로 설계합니다.
빠른 점검
- 구조체 크기 = 멤버 합이 아닐 수 있음
- 패딩은 정렬 때문에 생김
- 큰 필드를 앞에 두면 줄어들 수 있음
- 바이너리 직렬화는 필드 단위로 보는 편이 안전
주의할 점
#pragma pack으로 패딩을 강제로 없애는 것은 마지막 수단에 가깝습니다. 메모리 배치를 맞출 수는 있지만, 접근 비용과 이식성 부담이 같이 따라오기 때문에 "네트워크/파일 포맷과 정확히 맞춰야 하는 경우"가 아니면 먼저 설계를 다시 보는 편이 좋습니다.
참고 링크
2 sources