__attribute__
님의 코드에서 보이는 __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로 채워지게되어 낭패입니다. 따라서 확실한 경우 아니면
위처럼 사용하면됩니다.