1. 程式人生 > >pragma pack和記憶體對齊

pragma pack和記憶體對齊

概述

記憶體對齊和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的整數倍。