관리 메뉴

kisoo

#pragma pack() 엿보기 본문

01.About Programming /9..VC++

#pragma pack() 엿보기

JamesK78 2009. 2. 4. 10:10

pack 지시자는 이후부터 선언되는 구조체의 정렬 방식을 지정한다. 프로젝트 설정 대화상자에서 구조체 정렬 방식을 각 모듈별로 조정할 수 있지만 pack 지시자는 소스의 중간에서 원하는 구조체에 대해 정렬 방식을 변경할 수 있도록 한다는 점이 다르다. 이 지시자를 사용하면 같은 소스에 있는 두 구조체를 다른 방식으로 정렬할 수 있다. 다음 선언문을 보자.

 

#pragma pack(2)

struct st1 { short s; int i; };

#pragma pack(4)

struct st2 { short s; int i; };

 

이렇게 선언하면 st1 구조체는 2바이트 정렬되므로 6바이트를 차지하며 st2는 4바이트 정렬되므로 8바이트를 차지한다. 프로젝트 설정에 지정된 정렬값을 다른 값으로 바꾸고 싶을 때 pack(n) 지시자의 괄호안에 원하는 값을 적어주면 된다. 정렬값의 디폴트는 8이며 n을 생략하여 pack()이라고만 적으면 디폴트 정렬값으로 돌아간다.

pack(n)으로 정렬값을 변경하면 이후부터 선언되는 구조체는 이 정렬값의 영향을 받는다. 만약 특정 구조체에 대해서만 임시적으로 원하는 정렬값을 적용한 후 원래의 정렬값으로 돌아오려면 변경하기 전에 원래 값을 보관해 두어야 하는데 이 때는 push, pop 명령을 사용한다. 컴파일러는 내부에 정렬값 저장을 위한 스택을 유지하고 있으며 이 스택에 정렬 상태를 LIFO 원칙에 따라 저장하고 다시 빼내올 수 있다.

pack(push, n) 명령은 현재의 정렬 상태를 스택에 저장하면서 정렬값을 n으로 변경하는데 n을 생략하면 현재 정렬값을 스택에 저장하기만 한다. pack(pop,n)은 스택의 최상단에 있는 정렬값을 제거하고 새로운 정렬값을 n으로 변경하는데 n을 생략하면 스택에서 꺼낸 정렬값을 새로운 정렬값으로 설정한다. push는 저장과 동시에 다른 값으로 변경하는 경우가 많으므로 보통 n과 함께 쓰며 pop은 저장된 값을 복구시킬 때 사용하는 경우가 많으므로 보통 단독으로 사용한다. push, pop은 원하는만큼 중첩해서 사용할 수 있다. 다음 코드를 보자.

 

#pragma pack(2)

struct st1 { short s; int i; };                   // 2바이트 정렬

#pragma pack(push,4)                        // 푸시하면서 4바이트 정렬로 바꿈

struct st2 { short s; int i; };                   // 4바이트 정렬

#pragma pack(pop)                             // 원래 정렬값 복원

struct st3 { short s; int i; };                   // 2바이트 정렬

 

최초 정렬값 2를 가지는 상태에서 4로 변경하면서 원래 정렬 상태인 2를 스택에 푸시해 두었다. 그래서 st2 구조체를 선언한 후 다시 팝하면 정렬 상태 2로 복구될 것이다. 어떤 구조체가 반드시 특정 정렬 상태를 가져야 한다면 pack(push, n) 지시자로 원래 정렬상태를 유지하면서 설정을 잠시 변경할 수 있다. 예를 들어 어떤 파일을 읽어야 하는데 이 파일의 헤더가 구조체로 되어 있고 이 구조체는 반드시 1바이트로 정렬되어야 한다면 다음과 같이 이 구조체를 선언해야 한다.

 

#pragma pack(push,1)

struct Header

{

     char Magic[2];

     int Version;

     char NumRecord;

     double xsize, ysize;

};

#pragma pack(pop)

 

구조체를 선언하기 전에 정렬 상태를 1바이트로 바꾸되 이전의 정렬 상태는 스택에 푸시해 두었으며 구조체 선언이 끝난 후 다시 원래대로 정렬값을 복구한다. 이렇게 하지 않으면 Header 구조체는 프로젝트 설정대로 정렬되어 버리므로 이 구조체로는 파일을 제대로 읽을 수 없을 것이다.

 

출처 : www.winapi.co.kr

 

사용)

#pragma pack(1)

struct A {};

struct B {};

struct C {};

#pragma pack()


Comments