Computer >> 컴퓨터 >  >> 프로그래밍 >> C 프로그래밍

C/C++에서 구조체의 sizeof 크기가 멤버별 크기의 합과 다른 이유

C/C++에서 sizeof() 연산자로 구조체의 크기를 확인하면, 그 결과가 각 멤버의 크기를 단순히 더한 값과 항상 일치하지 않는 경우가 있습니다. 이는 컴파일러가 메모리 정렬(alignment) 문제를 방지하기 위해 패딩(padding)이라 불리는 여분의 바이트를 삽입하기 때문입니다.

패딩은 구조체 멤버 뒤에 더 큰 크기의 멤버가 이어질 때, 또는 구조체의 맨 끝에 추가됩니다. 컴파일러마다 적용하는 정렬 제약 조건이 다르며, C 표준에서도 구조체의 전체 정렬 방식은 구현(implementation)에 따라 달라질 수 있음을 명시하고 있습니다.

케이스 1: int → double → short 순서

이 경우 double 타입의 z는 8바이트로 int x(4바이트)보다 큽니다. 따라서 x 뒤에 4바이트의 패딩이 추가됩니다. 또한 short 타입의 y는 메모리에서 2바이트를 차지하므로, 구조체의 끝에 추가로 6바이트의 패딩이 붙게 됩니다.

예제 코드

#include <stdio.h>
struct myStruct {
   int x;      // 정수는 4바이트 차지, 뒤에 패딩 4바이트
   double z;   // double의 크기는 8바이트, 패딩 없음
   short int y; // short의 크기는 2바이트, 뒤에 패딩 6바이트
};
main() {
   printf("Size of struct: %d", sizeof(struct myStruct));
}

실행 결과

Size of struct: 24

케이스 2: double → int → short 순서

이번에는 double이 가장 먼저 선언되어 8바이트를 차지합니다. 그다음 int x(4바이트)가 추가되면서 뒤에 4바이트의 여유 공간이 생깁니다. short y가 추가될 때 이 여유 공간 안에 배치될 수 있으므로, 별도의 끝 패딩 없이 전체 크기는 16바이트가 됩니다.

예제 코드

#include <stdio.h>
struct myStruct {
   double z;    // double의 크기는 8바이트, 패딩 없음
   int x;       // 정수는 4바이트 차지, 뒤에 패딩 4바이트
   short int y; // short의 크기는 2바이트, 남은 공간에 배치
};
main() {
   printf("Size of struct: %d", sizeof(struct myStruct));
}

실행 결과

Size of struct: 16

케이스 3: double → short → int 순서

세 번째 경우 역시 16바이트의 메모리를 사용하지만, 멤버 배치 순서가 다릅니다. 첫 번째 멤버가 double이므로 가장 먼저 배치되고, 그다음 short 타입 데이터가 추가됩니다. 이후 int가 들어올 때 정렬 조건에 맞춰 배치되며, short 뒤에는 정렬용 패딩이 존재하지만 int 뒤에는 추가적인 패딩이 필요하지 않습니다.

예제 코드

#include <stdio.h>
struct myStruct {
   double z;    // double의 크기는 8바이트, 패딩 없음
   short int y; // short의 크기는 2바이트, 뒤에 정렬용 패딩
   int x;       // 정수는 4바이트 차지, 뒤에 패딩 없음
};
main() {
   printf("Size of struct: %d", sizeof(struct myStruct));
}

실행 결과

Size of struct: 16

정리 및 실무 팁

같은 멤버들로 구성된 구조체라도 선언 순서에 따라 크기가 24바이트에서 16바이트까지 달라질 수 있습니다. 따라서 메모리를 효율적으로 사용하려면 크기가 큰 멤버부터 작은 멤버 순으로 선언하는 것이 좋습니다. 또한 특수한 상황에서는 #pragma pack 지시문이나 컴파일러별 패킹 옵션을 사용해 패딩을 최소화할 수 있지만, 이 경우 정렬되지 않은 메모리 접근으로 인한 성능 저하나 이식성 문제가 발생할 수 있으므로 주의해야 합니다.