2011/12/29

淺談 c/c++ 使用 __attribute__

GNU C擴展的__attribute__ 機制被用來設置函數、變量、類型的屬性,其用得較多的是處理字節對齊的問題。

__attribute__ 的語法為:__attribute__ ((語法列表))

參數aligned(number) [number為最小對齊的字節數]是用得較多的一個。
另一個是參數packed 表示「使用最小對齊」方式,即對變量是字節對齊,對於域是位對齊。

Example:

#include
struct A{
char a;
int b;
unsigned short c;
long d;
unsigned long long e;
char f;
};

struct B{
char a;
int b;
unsigned short c;
long d;
unsigned long long e;
char f;
}__attribute__((aligned));

struct C{
char a;
int b;
unsigned short c;
long d;
unsigned long long e;
char f;
}__attribute__((aligned(1)));

struct D{
char a;
int b;
unsigned short c;
long d;
unsigned long long e;
char f;
}__attribute__((aligned(4)));

struct E{
char a;
int b;
unsigned short c;
long d;
unsigned long long e;
char f;
}__attribute__((aligned(8)));

struct F{
char a;
int b;
unsigned short c;
long d;
unsigned long long e;
char f;
}__attribute__((packed));

int main(int argc, char **argv)
{
printf("A = %d, B = %d, C = %d, D = %d, E = %d, F = %d\n",
sizeof(struct A), sizeof(struct B), sizeof(struct C), sizeof(struct D), sizeof(struct E), sizeof(struct F));
return 0;
}

在一個32位機上運行結果如下:

[root@root]# gcc -o align align.c
[root@root]# ./align
A = 28, B = 32, C = 28, D = 28, E = 32, F = 20

我們看到,最後一個struct F,1 + 4 + 2 + 4 + 8 + 1 = 20,因為使用了__attribute__((packed)); 來表示以最小方式對齊,所以結果剛好為20。

而第一個struct A,因為什麼也沒有跟,採用默認處理方式:4(1) + 4 + 4(2) + 4 + 8 + 4(1) = 28,括號中是其成員本來的大小。與此相似的是struct D。

接下來看struct E,採用8個字節的方式來對齊:8(1+4+2 ,即a, b, c)+ 8(4, d) + 8 + 8(1, f) = 32。

而在struct C中,試圖使用__attribute__((aligned(1))) 來使用1個字節方式的對齊,不過並未如願,仍然採用了默認4個字節的對齊方式。

在struct B中,aligned沒有參數,表示「讓編譯器根據目標機制採用最大最有益的方式對齊"——當然,最有益應該是運行效率最高吧,呵呵。其結果是與struct E相同。

在對結構的大小並不關注的時候,採用默認對齊方式或者編譯器認為最有益的方式是最常見的,對於一些對結構空間大小要求嚴格,例如定義一個數據包報頭的時候,明白結構的對齊方式,就非常有用了。

沒有留言: