1. 문제 개요
C++에서 sizeof
연산자를 사용하면 구조체 크기가 예상한 멤버 크기의 합보다 큰 경우가 많습니다. 이는 메모리 정렬(alignment)과 패딩(padding) 때문입니다. 본 글에서는 이 현상의 원인과 해결 방법을 살펴보겠습니다.
2. 메모리 정렬과 패딩의 원리
2.1 메모리 정렬이란?
메모리 정렬은 CPU가 데이터를 더 효율적으로 읽고 쓰기 위해, 데이터를 특정 바이트 경계에 맞춰 배치하는 방식입니다.
예를 들어, 4바이트 정수는 주소가 4의 배수로 정렬되면 CPU가 한 번의 읽기로 데이터를 처리할 수 있습니다.
2.2 구조체에서의 패딩
구조체의 멤버는 메모리 정렬을 만족하기 위해 사이에 패딩(추가 공간)이 삽입됩니다. 다음은 예시입니다:
struct Example {
char a; // 1 byte
// 3 bytes padding
int b; // 4 bytes
};
위 구조체의 크기는 sizeof(Example) = 8
입니다. char
는 1바이트이지만, int
가 4바이트 정렬을 요구하므로 3바이트 패딩이 추가됩니다.
3. 정렬 방식에 따른 구조체 크기 비교
아래는 32비트 시스템에서의 예제입니다:
struct X {
short s; // 2 bytes
// 2 bytes padding
int i; // 4 bytes
char c; // 1 byte
// 3 bytes padding
};
구조체 X
의 크기는 12바이트입니다. 각 멤버의 정렬 요구 사항에 따라 패딩이 추가되었습니다.
4. 최적화 방법
4.1 멤버 순서 조정
구조체 멤버를 크기 순으로 정렬하면 패딩을 줄일 수 있습니다.
예를 들어, 다음과 같이 멤버를 정렬합니다:
struct Optimized {
int i; // 4 bytes
short s; // 2 bytes
char c; // 1 byte
// 1 byte padding
};
sizeof(Optimized) = 8
로 줄어듭니다.
4.2 #pragma pack
사용
컴파일러의 #pragma pack
지시어로 패딩을 최소화할 수 있습니다. 하지만, 성능 저하와 CPU 예외 발생 가능성을 유의해야 합니다.
#pragma pack(1)
struct Packed {
char a; // 1 byte
int b; // 4 bytes
};
#pragma pack()
5. 결론
구조체 크기가 예상보다 큰 이유는 메모리 정렬과 패딩 때문입니다. 멤버 정렬 최적화와 #pragma pack
을 활용하여 크기를 줄일 수 있지만, 성능 저하와 호환성 문제를 고려해야 합니다. 이러한 원리를 이해하면 더 효율적인 코드 작성이 가능합니다.