Embedded System/Software

__attribute__

SuperMjs 2009. 7. 24. 18:01

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

위처럼 사용하면됩니다.