結構體的位元組對齊
在用sizeof運算子求算某結構體所佔空間時,並不是簡單地將結構體中所有元素各自佔的空間相加,這裡涉及到記憶體位元組對齊的問題。
1) 結構體變數的首地址能夠被其最寬基本型別成員的大小所整除;
2) 結構體每個成員相對結構體首地址的偏移量都是成員大小的整數倍;
3) 結構體的總大小為結構體最寬基本型別成員大小的整數倍。
型別 | int | short | long | char | bool | float | double | 指標 | 列舉 |
位元組 | 4 | 2 | 4 | 1 | 1 | 4 | 8 | 4 | 4 |
下面看一下sizeof在計算結構體大小的時候具體是怎樣計算的:
1.test1 空結構體
typedef struct node
{
}S;
則sizeof(S)=1。
2.test2
typedef struct node1 { int a; char b; short c; }S1;
則sizeof(S1)=8。(int)4+(char)1+(填充)1+(short)2=8,且能被(成員最寬型別)4整除。
4.test4 含有靜態資料成員
typedef struct node3
{
int a;
short b;
static int c;
}S3;
則sizeof(S3)=8。(int)4+(short)2=6+(填充)2=8,能被(成員最寬型別)4整除。
這裡結構體中包含靜態資料成員,而靜態資料成員的存放位置與結構體例項的儲存地址無關(注意只有在C++中結構體中才能含有靜態資料成員,而C中結構體中是不允許含有靜態資料成員的)。
5.test5 結構體中含有結構體
typedef struct node4
{
bool a;
S1 s1;
short b;
}S4;
則sizeof(S4)=16。(bool)1+(填充3)+(S1)8+(short)2=14+(填充)2=16,能被(成員最大寬度S1的寬度)4整除。
S1佔8位元組,而S1中最長資料型別為int,佔4個位元組。
6.test6
若在程式中使用了#pragma pack(n)命令強制以n位元組對齊時,預設情況下n為8。則比較n和結構體中最長資料型別所佔的位元組大小,取兩者中小的一個作為對齊標準。
如果在程式開頭使用命令#pragma pack(4),對於下面的結構體
typedef struct node5
{
bool a;
S1 s1;
double b;
int c;
}S5;
則sizeof(S5)=24。因為強制以4位元組對齊,而S5中最長資料型別為double,佔8位元組,因此以4位元組對齊。在記憶體中存放方式為:
|-----------a--------| 4位元組
|--------s1----------| 4位元組
|--------s1----------| 4位元組
|--------b-----------| 4位元組
|--------b-----------| 4位元組
|---------c----------| 4位元組