概述
內存對齊和CPU有關係,可以認爲內存對齊的大小就是CPU一次讀取內存的大小,例如32CPU一次讀取4字節,那麼內存的對齊方式就4字節,64位就是8字節。本質上是保證CPU使用盡量少的次數將某一個變量取出來。關於結構體內存對齊的方式,只需要把握兩點即可:
- 每個成員變量的對齊原則,即成員的偏移量計算。參見成員對齊原則。
- 整個結構體的對齊原則,即結構大小的計算。參見整體對齊原則。
pragma pack(n)的作用
上面說了,編譯默認對齊方式是4字節(32位系統)或者8字節(64)位系統,但是通過pragma pack可以自己定義內存的對齊方式。
#pragma pack(n) // n = 1,2,4,8,16......
實例
#include <stdio.h>
//#pragma pack(2)
//#pragma pack(4)
struct node{
char f;
int e;
short a;
char d;
};
int main(void)
{
node n;
printf("len=%d\n", sizeof(node));
return 0;
}
// 輸出:
當 #pragma pack(2) 時, len = 10
當 #pragma pack(4) 時, len = 12
當 #pragma pack(8) 時, len = 12
當 不使用#pragma pack(n) 時, len = 12
內存對齊的原則
對照上面的實例,下面講解具體原則。
1、成員對齊原則
對於結構體的各個成員,第一個成員的偏移量是0,後面的成員其當前偏移量必須是當前成員類型大小的整數倍。
上面的案例中,在默認的對齊方式中,e的偏移量必須是4的倍數,因爲e佔4個字節,所以f要補齊3個字節,使e偏移量爲4。f偏移量爲0,a的偏移量爲2的倍數是8,d的偏移量爲1的倍數,爲11。
2、整體對齊原則
結構體內所有數據成員各自內存對齊後,結構體本身還要進行一次內存對齊,保證整個結構體佔用內存大小是結構體內最大數據成員的最小整數倍。
上面可知,d的偏移量爲11,其實11個字節就可以存下,但是整體的大小必須是最大成員e的倍數,因此至少爲12,d需要補齊一個字節。
3、自定義對齊方式
即使用#pragma pack(n)預編譯指令。
如果程序中使用#pragma pack(n),則忽略上面的兩個原則。只需遵循以下面兩個新原則:
1、成員對齊
- 當 n >= 成員變量的大小, 該變量的偏移量仍然是自身大小的整數倍。
- 當 n < 成員變量的大小, 該變量的偏移量是n的整數倍。
2、整體對齊
- 當 n >= 最大成員變量的大小, 整個結構體大小仍然是最大成員的整數倍。
- 當 n < 最大成員變量的大小, 整個結構體大小是n的整數倍。