pragma pack和記憶體對齊
阿新 • • 發佈:2018-12-17
概述
記憶體對齊和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的整數倍。