朗訊的筆試題是這樣的:
Typedef union student
{
Char name[10];
Long sno;
Char sex;
Float score [4];
} STU;
Main ()
{
STU a[5];
Printf(“%d/n”,sizeof(a);
}
答案是80 ,因爲union是可變的以其成員中最大的成員作爲 該union的大小!
但是換成是 struct又是多少呢?
Typedef struct student
{
Char name[10];
Long sno;
Char sex;
Float score [4];
} STU;
Main ()
{
STU a[5];
Printf(“%d/n”,sizeof(a);
}
答案是 180 ????爲什麼不是 (10+4+1+16)*5=155? 因爲struct 有個叫對齊方式的問題:
不對齊的數據存取在x86上影響速度,因爲在不對齊的時候,對於小的可能會影響 其效率,對齊即是多分配一些字節,填充無用數據,以空間的損失來換取消率。
struct是一種複合數據類型,其構成元素既可以是基本數據類型(如int、long、float等)的變量,也可以是一些複合數據類型(如array、struct、union等)的數據單元。對於結構體,編譯器會自動進行成員變量的對齊,以提高運算效率。缺省情況下,編譯器爲結構體的每個成員按其自然對齊(natural alignment)條件分配空間。各個成員按照它們被聲明的順序在內存中順序存儲,第一個成員的地址和整個結構的地址相同。
自然對齊(natural alignment)即默認對齊方式,是指按結構體的成員中(類型)size最大的成員作爲基本的分配單元,而且與其順序有這密切的聯繫。
例如:
struct naturalalign
{
char a;
short b;
char c;
};
在上述結構體中,size最大的是short,其長度爲2字節,因而結構體中的char成員a、c都以2爲單位對齊,sizeof(naturalalign)的結果等於6;
如果改爲:
struct naturalalign
{
char a;
int b;
char c;
};
其結果顯然爲12。
那麼再回到到原題:結構體中,size最大的是long,size是 4,所以,按照順序,Char name[10];12個字節;Long sno; 4個字節;Char sex; 4個字節(這裏對齊了);Float score [4]; 16個字節。於是(12+4+4+16)×5=180,就是了!
剛纔還說過,與順序有關,呵呵,我們改一下:
Typedef struct student
{
Char name[10];
Char sex;
Long sno;
Float score [4];
} STU;
Main ()
{
STU a[5];
Printf(“%d/n”,sizeof(a);
}
Main ()
{
STU a[5];
Printf(“%d/n”,sizeof(a);
}
答案是:160. 爲什麼,只是換了順序而已呀?關鍵就在順序上。
結構體中,size最大的是long,size是 4,所以,按照順序,Char name[10];12個字節;但是這12中多分配的2個字節可以包含後面的Char sex; (問題就在這);Float score [4]; 16個字節。於是(12+4+16)×5=160,就是了!
所以要小心呀!
2.2指定對齊
一般地,可以通過下面的方法來改變缺省的對齊條件:
· 使用僞指令#pragma pack (n),編譯器將按照n個字節對齊;
· 使用僞指令#pragma pack (),取消自定義字節對齊方式。
注意:如果#pragma pack (n)中指定的n大於結構體中最大成員(類型)的size,則其不起作用,結構體仍然按照size最大的成員進行對齊。
例如:
#pragma pack (n)
struct naturalalign
{
char a;
int b;
char c;
};
#pragma pack ()
當n爲4、8、16時,其對齊方式均一樣,sizeof(naturalalign)的結果都等於12。而當n爲2時,其發揮了作用,使得sizeof(naturalalign)的結果爲6。
在VC++ 6.0編譯器中,我們可以指定其對齊方式(見圖1),其操作方式爲依次選擇projetct > setting > C/C++菜單,在struct member alignment中指定你要的對界方式。
圖1:在VC++ 6.0中指定對界方式
另外,通過__attribute((aligned (n)))也可以讓所作用的結構體成員對齊在n字節邊界上,但是它較少被使用,因而不作詳細講解。
Typedef struct student
{
Char name[10];
Char sex;
Long sno;
Float score [4];
} STU;
Main ()
{
STU a[5];
Printf(“%d/n”,sizeof(a);
}
Main ()
{
STU a[5];
Printf(“%d/n”,sizeof(a);
}
答案是:160. 爲什麼,只是換了順序而已呀?關鍵就在順序上。
結構體中,size最大的是long,size是 4,所以,按照順序,Char name[10];12個字節;但是這12中多分配的2個字節可以包含後面的Char sex; (問題就在這);Float score [4]; 16個字節。於是(12+4+16)×5=160,就是了!
所以要小心呀!
2.2指定對齊
一般地,可以通過下面的方法來改變缺省的對齊條件:
· 使用僞指令#pragma pack (n),編譯器將按照n個字節對齊;
· 使用僞指令#pragma pack (),取消自定義字節對齊方式。
注意:如果#pragma pack (n)中指定的n大於結構體中最大成員(類型)的size,則其不起作用,結構體仍然按照size最大的成員進行對齊。
例如:
#pragma pack (n)
struct naturalalign
{
char a;
int b;
char c;
};
#pragma pack ()
當n爲4、8、16時,其對齊方式均一樣,sizeof(naturalalign)的結果都等於12。而當n爲2時,其發揮了作用,使得sizeof(naturalalign)的結果爲6。
在VC++ 6.0編譯器中,我們可以指定其對齊方式(見圖1),其操作方式爲依次選擇projetct > setting > C/C++菜單,在struct member alignment中指定你要的對界方式。
圖1:在VC++ 6.0中指定對界方式
另外,通過__attribute((aligned (n)))也可以讓所作用的結構體成員對齊在n字節邊界上,但是它較少被使用,因而不作詳細講解。