細說 Pragma Pack n 與記憶體對齊

2021-07-13 11:22:56 字數 2923 閱讀 7339

關於 #pragma pack(n)與復合型別的資料(常見於結構體、陣列等)對其方式約束,流傳兩種型別的解釋:

每個特定平台上的編譯器都有自己的預設「對齊係數」(也叫對齊模數)。程式設計師可以通過預編譯命令#pragma pack(n),n=1,2,4,8,16來改變這一係數,其中的n就是你要指定的「對齊係數」。

規則:

1.資料成員對齊規則:結構(struct)(或聯合(union))的資料成員,第乙個資料成員放在offset為0的地方,以後每個資料成員的對齊按照 #pragma pack(n)指定的對齊係數n 與這個資料成員自身長度兩者,最小的那個進行,即 min(n,sizeof(結構成員));

2. 結構(或聯合)的整體對齊規則:在資料成員完成各自對齊之後,結構(或聯合)本身也要進行對齊,對齊將按照#pragma pack指定的數值和結構(或聯合)最大資料成員長度兩者中,比較小的那個進行。

demo:據說是intel和微軟和本公司同時出現的面試題,曾經也是引**熱的討論,

#pragma pack(8) 

struct s1;

struct s2;

#pragma pack()

1.sizeof(s2) = ?

2.s2的c後面空了幾個位元組接著是d?

答案:

①sizeof(s2)結果為24.

②s2的c後面空了幾個位元組接著是d?==>3位元組

這裡邊宣告下,題意sizeof(short )== 2,sizeof(long )== 4,sizeof(long long )== 8,

說明:

成員對齊有乙個重要的條件,即每個成員分別對齊.即每個成員按自己的方式對齊.

也就是說上面雖然指定了按8位元組對齊,但並不是所有的成員都是以8位元組對齊.其對齊的規則是,每個成員按其型別的對齊引數(通常是這個型別的大小)和指定對齊引數(這裡是8位元組)中較小的乙個對齊.並且結構的長度必須為所用過的所有對齊引數的整數倍,不夠就補空位元組.==>這裡見上邊的解釋一

關注下struct s2成員d,型別為struct s1,是個結構體型別;對於結構來說,它的預設對齊方式就是它的所有成員使用的對齊引數中最大的乙個,s1中所用成員對齊引數最大==4。所以,成員d就是按4位元組對齊。==>這裡可以適當套用下解釋一的第二條

下邊抽象下s1、s2成員在記憶體中的排布:

s1的記憶體布局:11**,1111, ==>a與b之間有2位元組的資料填充;

s2的記憶體布局:1***,11**,1111,****11111111 ==>c,d之間存在3個位元組的資料填充,

繼續例項化幾個案例:

#pragma pack(4)

struct node;

記憶體排布:1111,1*,11,1, * * * ,==12位元組

char f,與pack(4)指定的4 ,取最小值對齊,so按1位元組對齊,前邊不需要填充;

short int a與4比較取最小 2位元組對齊,so前邊的char f;需要填充乙個位元組;

char b與4,知按1位元組對齊,前方不需要short int a不需要填充;

其中,最占地的成員為int e,sizeof(int)==4位元組;

接下來是資料結構struct node的整體對齊填充,由解釋一種的規則2知,min(sizeof(int),4)==4,就是說該資料結構整體需要4位元組對齊,即最後還需要填充3位元組,來確保符合規則約束。

#pragma pack(4)

struct node;

記憶體排布:1***,1111,11,1,*,==12位元組

int e與4比較知,知該成員按4位元組對齊,前邊的char f需要填充3位元組資料;

short int a與4比較,知該成員按2位元組對齊,前方的int e不需要填充;

char b與4比較,知該成員按1位元組對齊,前邊的short int a不需要填充,

最後資料結構整體需要按4位元組對齊,需要在尾部繼續填充乙個資料;

#pragma pack(2)

struct node;

記憶體排布:1*,1111,11,1,* ==10位元組

int e與2比較知,知該成員按2位元組對齊,前邊的char f需要填充1位元組資料;

short int a與2比較,知該成員按2位元組對齊,前方的int e不需要填充;

char b與2比較,知該成員按1位元組對齊,前邊的short int a不需要填充,

最後資料結構整體需要按2位元組對齊,需要在尾部繼續填充乙個資料;

#pragma pack(1)

struct node;

記憶體排布:1,1111,11,1, ==8位元組

int e與1比較知,知該成員按1位元組對齊,前邊的char f需要填充0位元組資料;

short int a與1比較,知該成員按1位元組對齊,前方的int e不需要填充;

char b與1比較,知該成員按1位元組對齊,前邊的short int a不需要填充,

最後資料結構整體需要按1位元組對齊,需要在尾部繼續填充乙個資料;

對於陣列,比如:

char a[3];這種,它的對齊方式和分別寫3個char是一樣的.也就是說它還是按1個位元組對齊.

如果寫: typedef char array3[3];

array3這種型別的對齊方式還是按1個位元組對齊,而不是按它的長度. 不論型別是什麼,對齊的邊界一定是1,2,4,8,16,32,64….中的乙個.

以上,有情況及時溝通….

Pragma Pack n 與記憶體分配

pragma pack n 解釋一 每個特定平台上的編譯器都有自己的預設 對齊係數 也叫對齊模數 程式設計師可以通過預編譯命令 pragma pack n n 1,2,4,8,16來改變這一係數,其中的n就是你要指定的 對齊係數 規則 1 資料成員對齊規則 結構 struct 或聯合 union 的...

Pragma Pack n 與記憶體分配

pragma pack n n 位元組的對齊方式 vc 對結構的儲存的特殊處理確實提高 cpu 儲存變數的速度,但是有時候也帶來 了一些麻煩,我們也遮蔽掉變數預設的對齊方式,自己可以設定變數的對齊方式。vc 中提供了 pragma pack n 來設定變數以 n 位元組對齊方式。n 位元組對齊就是說...

Pragma Pack n 與記憶體分配

pragma pack n 解釋一 每個特定平台上的編譯器都有自己的預設 對齊係數 也叫對齊模數 程式設計師可以通過預編譯命令 pragma pack n n 1,2,4,8,16來改變這一係數,其中的n就是你要指定的 對齊係數 規則 1 資料成員對齊規則 結構 struct 或聯合 union 的...