본문 바로가기

프로그래밍

[프로그래밍] struct pack command (구조체 최적화 하기)

구조체를 어떻게 선언하느냐에 따라 일반적으로 용량차이가 발생하게 된다.

typedef struct tagBITMAPFILEHEADER 
{
  WORD         bfType; //4바이트 할당
  DWORD      bfSize; //4바이트 할당
  WORD         bfReserved1; //2바이트 할당
  WORD         bfReserved2; //2바이트 할당
  DWORD      bfOffBits; //4바이트 할당
} BITMAPFILEHEADER;

위와같은 구조체는 실제크기는 14바이트이지만 컴파일러는 16바이트로 처리하게 된다. 그 원리는 첫번째 워드가 실제크기는 2바이트지만 효율면에서 4바이트로 처리하는것이 좋기 때문에 4바이트로 할당을 하게 된다. 그리고 3번째 4번째 WORD는 4바이트 상위워드와 하위워드에 넣어 할당을 하게 되므로 총 합이 16바이트가 되게 된다.

일반적으로 이러한 구조체를 사용하는데 크게 문제가 되지 않지만 간혹 문제가 발생 할 경우가 생기게 마련이다. 예를 들어 비트맵같은경우에는 fread로 위에 구조체 내용을 채우는것이 효율이 좋으므로 아래와 같이 사용을 하게 된다.

fread((BYTE*)bitmap_file_header,1,sizeof(BITMAPFILEHEADER),fp);

하지만 sizeof(BITMAPFILEHEADER) 가 16이 되기때문에 문제가 발생하게 된다.

이럴경우에

GCC일 경우에는 __attribute__((packed)) 를  아래와 같이 사용하고

typedef struct __attribute__((packed)) tagBITMAPFILEHEADER // tagBITMAPFILEHEADER 이게 앞에 오면 안된다.
{
  WORD         bfType; //4바이트 할당
  DWORD      bfSize; //4바이트 할당
  WORD         bfReserved1; //2바이트 할당
  WORD         bfReserved2; //2바이트 할당
  DWORD      bfOffBits; //4바이트 할당
} BITMAPFILEHEADER;

win32에서는 아래와 같이 사용하면 되겠다.

#pragma pack(1) // 정렬 할 크기를 괄호안에 넣는다.


위 2가지 경우를 대비한 헤더를 만들어보면 아래와 같이 하면 된다.

#ifndef __GNUC__
#pragma pack(1)
#define __attribute__(a)
#endif

참으로 알면 알수록 어려워지는 C언어... 하지만 재밌다.~~~