Neoteny

구조체 패킹

2007. 11. 6. 16:26
반응형

구조체 패킹에 대해서 알아보겠다.

우선 간단히 이런 구조체가 있다고 생각해보자.

typedef struct tagSTRUCTA
{
  int A;
  char B[2];
  int C;
} STRUCTA;

이런 구조체는 사이즈가 몇일까..
int는 하나에 4바이트. char는 하나에 1바이트이니까, 쉽게 보면 10byte가 나오는것이 정상일 것이라고 생각하게 된다.

하지만 이 경우는 실제 sizeof 키워드를 사용해서 길이를 계산하면 10byte가 나오는게 아니라 12byte가 나오게 된다.

이 이유는 메모리에서 데이터를 가져올때 int형 을 기준으로 4바이트 단위로 메모리를 한꺼번에 가져오는것이 가장 속도면에서 빠르기 때문에 구조체를 생성할 시에 기본적으로 4의 배수만큼 메모리를 할당하고 나머지 공간은 비워두게 된다.

그럼 빈공간은 어디에 위치하는가? B의 뒤인가?, C의 뒤인가?
B가 담기고 나면 2byte가 여유분이 생기게 된다. 하지만 C가 4바이트를 차지하기 때문에 B의 뒤에 C의 반쪽이 위치한다면 4의 배수만큼씩 움직이는 메모리에서는 2번 데이터를 가져와야 C를 찾아올수 있을 것이다.
즉. 정답은 B뒤에 빈공간 2Byte가 위치하는 것이다.

자 그럼 네트워크의 패킷이나, 바이너리 데이터의 경우를 살펴보자.
우리는 종종 네트워크 패킷이나 바이너리 데이터를 분석할때에 구조체를 정의하고 데이터를 넣은다음 스트림으로 바로 전송하게 된다.
이 경우 이런 빈공간이 위치하게 되면 개발자는 항상 네트워크 패킷에서 어디에서 빈공간이 나타나는지를 항상 염두해두어야 할 것이다. 뿐만아니라 데이터가 빈공간들로 인해 증가될 것이다.

이런 빈공간을 없애고 데이터를 저장하는 방법이 바로 pragma 키워드를 사용하는 것이다.
아래 코드를 보자.

#pragma pack(push) // 기존 바이트얼라인먼트 저장
#pragma pack(1)  // 바이트얼라인먼트를 1바이트로 설정
typedef struct tagSTRUCTA
{
  int A;
  char B[2];
  int C;
} STRUCTA;
#pragma pack(pop) // 기존 바이트얼라인먼트 복구

반응형