본문 바로가기
C++ 200제/코딩 IT 정보

[C++구조체] #Pragma pack(1) 지시어 이해하기

by vicddory 2017. 10. 4.

[C++구조체] #Pragma pack(1) 지시어 이해하기


Word Alignment(#pragma pack)


Word Alignment(#pragma pack)는 어려운 개념은 아니지만, 매우 중요한 개념입니다.


우리는 하나의 word가 4바이트란 건 알고 있습니다. 메모리 주소 체계도 4바이트로 이뤄지며, 0x01ab23cd와 같은 값은 0x01, 0xab, 0x23, 0xcd로 각각 분리되어 저장되는 것도 알고 있죠. 알아야 #pragma pack도 이해할 수 있습니다.


그 저장되는 방법은 little Endian과 Big Endian으로 이 경우엔 0x01이 맨 뒤, 또는 맨 앞에 저장될 겁니다. 다소, 부정확한 의미가 될 순 있지만, 0x01이 저장된 주소가 N(1001) 번지라면 그다음 주소는 N+1이 됩니다.


그렇지만 N+1에는 문제가 있습니다.


C언어에서 아래와 같은 구조체를 만들어 확인해 봅시다.


1
2
3
4
5
6
struct Foo {
   char x ;  // 1 byte
   int y ;     // 4 byte, must be word-aligned
   char z ;  // 1 byte
   int w ;    // 4 byte, must be word-aligned
};
cs


산술적으로 Foo 구조체는 10바이트이지만, 12바이트의 메모리가 필요합니다. 32비트 프로세서 기반에선 버스가 4바이트로 데이터를 읽어냅니다. #pragma pack의 맹점도 여기 있습니다.

다시 예를 들어, C언어에서 아래와 같은 구조체를 만들어 봅시다.


1
2
3
4
struct TestStruct{
    char mChar[4];
    int nInt;
} TS;
cs


위의 구조체를 SizeOf로 읽어내면 8바이트가 나오죠.


c구조체 pragma pack[[C++구조체] #Pragma pack 지시어 (1) 이해하기]


32비트 프로세서에서는 버스를 두 번만 움직여 구조체의 모든 정보를 읽을 수 있습니다. 헌데, 문제는 아래와 같이 구조체를 변경했을 경우입니다.


1
2
3
4
struct TestStruct{
    char mChar[6];
    int nInt;
} TS;
cs


char형 배열의 크기를 6으로 늘렸습니다. 논리적으로 계산했을 때, 10바이트가 할당됩니다. 근데, 과연 프로세스상에서도 10바이트가 할당될까요?


그러나 12바이트가 할당됩니다. 아래의 예제 코드를 실행해보면, 8과 12란 숫자가 콘솔 창에 나타납니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <stdio.h>
 
struct TestStructA{
    char mChar[4];
    int nInt;
}TSa;
 
struct TestStructB{
    char mChar[6];
    int nInt;
}TSb;
 
int main(void)
{
    int nSizeTSa, nSizeTSb;
    nSizeTSa = sizeof(TSa);
    nSizeTSb = sizeof(TSb);
 
    printf("%d, %d\n", nSizeTSb, nSizeTSb);
}
cs


즉, 데이터 처리를 위해 사용되는 버스가 4바이트이기 때문에, 9바이트 구조체도 12바이트로, 10바이트 구조체도 12바이트로, 11바이트 구조체도 12바이트로 할당됩니다.


이는, 프로그램의 규모가 거대해지고 array, enum, struct 사용이 많아질수록 낭비되는 양도 그에 비례해 증가한다는 겁니다.

9바이트를 위해 버스가 2번 이동해서 8바이트를 읽어낸 뒤, 남은 1바이트를 위해 한 번 더 움직이는 것도 비효율적이죠.


[C++구조체] #Pragma pack(1) 지시어 이해하기[C++ 전처리기] 지시어 이해하기


하지만, #pragma를 이용해 더욱 효율적인 코딩이 가능합니다.


1
2
3
4
5
6
7
8
#pragma pack(1)
 
struct TestStructA{
    char mChar[6];
    int nInt;
}TSa;
 
#pragma pack(pop)
cs


위와 같이 선언하면, 데이터 버스는 1바이트 단위로 동작합니다.


산술적 연산으로 계산 가능한 만큼 동작하게 됩니다. 다만, 1바이트로 동작하게 되면 그만큼 수행 속도가 느려지는 문제가 있으나, 최근의 컴퓨터들 사양을 훑어보면 큰 걱정은 안 하셔도 됩니다.


Word Alignment의 개념을 토대로 더욱 효율적인 코딩을 해보세요~


[C++구조체] #Pragma pack(1) 지시어 이해하기

댓글