爲了加快數據存取的速度,編譯器默認情況下會對結構體成員和結構體本身存儲位置進行處理,使其存放的起始地址是一定字節數的倍數,而不是順序存放,稱爲字節對齊.
(以下這3條規則摘自姜學鋒,周果清,劉君瑞老師共編的《C++程序設計》,寫得很好,在此表示感謝!) (個人認爲,這本書在這一節方面寫得要優於《深入理解計算機系統》)
設對齊字節數爲n(n = 1,2,4,8,16),每個成員內存長度爲Li,Max(Li)爲最大的成員內存長度,字節對齊規則是:
1. 結構體對象的起始地址能夠被Max(Li)所整除;
2. 結構體中每個成員相對於起始地址的偏移量,即對齊值應是min(n,Li)的倍數.若不滿足對齊值的要求,編譯器會在成員之間填充若干個字節;
3. 結構體的總長度值應是min(n,Max)(Li)的倍數,若不滿足總長度值的要求,編譯器在爲最後一個成員分配空間後,會在其後填充若干個字節. (VC默認的對齊字節數n=8)
//第一個範例
int main()
{
struct s {
int i;
char ch;
short c;
};
printf("%d", sizeof( struct s ));
return 0;
}
//結果爲:4+1+X+2=8 (X=1,滿足於對齊規則第2條)
//第二個範例
int main()
{
struct s {
char ch;
int i;
short c;
};
printf("%d", sizeof( struct s ));
return 0;
}
//結果爲:1+X+4+2+Y=12 (X=3,Y=2,分別滿足於對齊規則第2條和第3條)
//使用pragma pack(push,n)和pragma pop組合
//第三個範例
#pragma pack(push,2) //此處n=2,(相當於將VC默認的對齊字節數設定爲n=2)
int main()
{
struct s {
int i;
char ch;
short c;
};
#pragma pack(pop)
printf("%d", sizeof( struct s ));
return 0;
}
//結果爲:4+1+X+2=8(X=1,滿足於對齊規則第條)
//第四個範例
#pragma pack(push,4) //此處n=4,(相當於將VC默認的對齊字節數設定爲n=4)
int main()
{
struct s {
int i;
char ch;
short c;
};
#pragma pack(pop)
printf("%d", sizeof( struct s ));
return 0;
}
//結果爲:4+1+X+2=8(X=1,滿足於對齊規則第條)
//第五個範例
#pragma pack(push,8) //此處n=8,(相當於將VC默認的對齊字節數設定爲n=8)
int main()
{
struct s {
int i;
int y;
char ch;
short c;
};
#pragma pack(pop)
printf("%d", sizeof( struct s ));
return 0;
}
//結果爲:4+4+1+X+2=12(X=1,滿足於對齊規則第2條)