__attribute__는 GCC 컴파일러에 있는 메커니즘으로 컴파일러에게 추가적인 에러 체킹 같은 것을 하도록 지시하는 것이다.

형식 : __attribute__(x)
괄호 안의 x에는 가능한 몇 가지들이 있는데 특히, packed는 채우라는 의미이다:
typedef struct
{
    char a;
    int b;
} myST;

위 구조체의 sizeof(myST)는 8이다.
상식적으로 char =1byte, int = 4byte이므로 5가 나와야 하는데.. 
이런 문제 때문에 구조체를 가지고 작업할 경우 예상치 못한 버그로 고생을 가끔한다.
이런 현상이 생기는 이유는 현재 사용하고 있는 컴퓨터가 32비트이기 때문이다. 즉, CPU가 메모리 어드레스를 지정할 때 4바이트(32비트/8) 단위가 내부적으로 가장 최적화되어 빠른 데이터 접근을 가능하게 한다. 4바이트 배수 단위가 아닌 경우 당연히 접근은 가능하지만 속도 차이가 있어 디폴트로 저런 접근을 하도록 해 둔 것이다.

그럼, 메모리에 저 구조체가 잡힐 경우 어떻게 존재하느냐는 4바이트 단위로 채워지기 때문에 char a;는 1바이트이지만 4바이트를 할당해서 거기다 char a;를 담아둔다. 다음 int b;는 4바이트므로 그냥 4바이트를 할당한다. 이렇게 해서 8바이트의 크기가 필요한 것이다.

첫 char a;에서 1바이트를 제외한 나머지 3바이트는 어떤 걸로 채워질까? 의미없는 값이 채워진다. 그냥 공간만 예약되는 것이다. 그래서 이런 현상을 방지할 수 있도록 컴파일러는 __attribute__ (packed) 메커니즘을 두어서 우리가 예상한 (1바이트+4바이트) 크기가 되도록 빌드한다:
typedef struct
{
    char a;
    int b;
__attribute__((packed)) myST;

결국, 위 처럼 사용하게되면 컴파일러는 구조체 멤버의 실제 크기 만큼 할당한다. 그래서 정확한 5바이트가 나오게 된다. 물론, 속도는 약간 더 늦어진다.

여기에서 __attribute__라는 의미는 컴파일러에게 특성을 주겠다는 것을 의미하며 괄호 안은 여러 가지가 가능한데 여기서는 그 중 한가지인 구조체 정렬을 사용하겠다는 의미인 packed를 사용했다.

packed의 의미는 꽉 채우다라는 것인데 이 기능을 사용하지 않았을 경우 char a;는 실제 1바이트 외에 나머지 3바이트가 자리만 차지한 채 남아있다. 이런 비어있는 것들을 제거해서 구조체 멤버들이 빈 자리없이 꽉 채우라는 단어 의미이다. 이런 것을 구조체 정렬(alignment)이라고 한다.

위는 unix/linux의 GCC에서 사용하는 것이고 윈도우 상의 비주얼 씨의 경우는
#pragma pack(1)

처럼 사용한다. 괄호 안의 의미는 1바이트 단위까지 체크해서 빈 자리가 없도록 차곡차곡 채우라는 것이다. 4가 올 수도 있겠지만 그렇게 되면 가장 작은 단위가 4가되어 char 형 같은 경우 역시 4로 채워지게 되어 낭패이다. 따라서 확실한 경우 아니면 위 처럼 사용하면 된다.

출처: 지식IN(edson)

'Developer's Infos > Linux Programming' 카테고리의 다른 글

pci-driver  (0) 2011.10.10
add_wait_queue()/remove_wait_queue()/schedule() 설명 및 사용법  (0) 2011.10.10
[Linux] asmlinkage  (0) 2011.09.30
[Shared Memory] shmget() 공유 메모리 생성  (0) 2011.09.06
PCI Driver Flow  (0) 2011.09.05
Posted by 삼성동고양이