記憶體對齊及 pragma pack的使用

2021-07-11 23:46:46 字數 3102 閱讀 3932

在預設情況下,c編譯器為每乙個變數或是資料單元按其自然對界條件分配空間。

在結構中,編譯器為結構的每個成員按其自然對界(alignment)條件分配空間。各個成員按照它們被宣告的順序在記憶體中順序儲存(成員之間可能有插入的空位元組),第乙個成員的位址和整個結構的位址相同。

c編譯器預設的結構成員自然對界條件為「n位元組對齊」,n即該成員資料型別的長度。

如int型成員的自然對界條件為4位元組對齊,而double型別的結構成員的自然對界條件為8位元組對齊。若該成員的起始偏移不位於該成員的「預設自然對界條件」上,則在前乙個節面後面新增適當個數的空位元組。

c編譯器預設的結構整體的自然對界條件為:該結構所有成員中要求的最大自然對界條件。

若結構體各成員長度之和不為「結構整體自然對界條件的整數倍,則在最後乙個成員後填充空位元組。

例子1(分析結構各成員的預設位元組對界條界條件和結構整體的預設位元組對界條件):

struct

test

;

因為test結構體中,最大的成員為flaot x3,因些此結構體的自然對界條件為4位元組對齊。則結構體長度就為12位元組,記憶體布局為1100 1111 1000。

例子2:

#include 

<

stdio.h

>

//#pragma pack(2)

typedef

struct

testlength1;

intlength1

=sizeof

(testlength1);

//4個位元組對齊,占用位元組1111 1011 1000,length = 12

typedef

struct

testlength2;

intlength2

=sizeof

(testlength2);

//4個位元組對齊,占用位元組1000 1111 1100,length = 12

typedef

struct

testlength3;

intlength3

=sizeof

(testlength3);

//4個位元組對齊,占用位元組1100 1111 1100,length = 12

typedef

struct

testlength4;

intlength4

=sizeof

(testlength4);

//4個位元組對齊,占用位元組1111 1111,length = 8

intmain(

void

)

改變預設的對界條件(指定對界)

· 使用偽指令#pragma pack (n),c編譯器將按照n個位元組對齊。

· 使用偽指令#pragma pack (),取消自定義位元組對齊方式。

這時,對齊規則為:

1、資料成員對齊規則:結構(struct)(或聯合(union))的資料成員,第乙個資料成員放在offset為0的地方,以後每個資料成員的對齊按照#pragma pack指定的數值和這個資料成員自身長度中,比較小的那個進行

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

結合1、2推斷:當#pragma pack的n值等於或超過所有資料成員長度的時候,這個n值的大小將不產生任何效果。

因此,當使用偽指令#pragma pack (2)時,test結構體的大小為8,記憶體布局為11 11 11 10。

需要注意一點,當結構體中包含乙個子結構體時,子結構中的成員按照#pragma pack指定的數值和子結構最大資料成員長度中,比較小的那個進行進行對齊

例子如下:

#pragma pack(8)

struct s1;

struct s2;

#pragma pack()

sizeof(s2)的結果為24。s1的記憶體布局為1100 1111,s2的記憶體布局為1000 1100 1111 0000 1111 1111。

例子:

#include 

<

stdio.h

>

#pragma

pack(2)

typedef

struct

testlength1;

intlength1

=sizeof

(testlength1);

//2個位元組對齊,占用位元組11 11 10 11 10,length = 10

typedef

struct

testlength2;

intlength2

=sizeof

(testlength2);

//2個位元組對齊,占用位元組10 11 11 11 10,length = 10

typedef

struct

testlength3;

intlength3

=sizeof

(testlength3);

//2個位元組對齊,占用位元組11 11 11 11,length = 8

typedef

struct

testlength4;

intlength4

=sizeof

(testlength4);

//2個位元組對齊,占用位元組11 11 11 11,length = 8

intmain(

void

)

另外,還有如下的一種方式:

· __attribute((aligned (n))),讓所作用的結構成員對齊在n位元組自然邊界上。如果結構中有成員的長度大於n,則按照最大成員的長度來對齊。

· __attribute__ ((packed)),取消結構在編譯過程中的優化對齊,按照實際占用位元組數進行對齊。

以上的n = 1, 2, 4, 8, 16... 第一種方式較為常見。

pragma pack和記憶體對齊

記憶體對齊和cpu有關係,可以認為記憶體對齊的大小就是cpu一次讀取記憶體的大小,例如32cpu一次讀取4位元組,那麼記憶體的對齊方式就4位元組,64位就是8位元組。本質上是保證cpu使用盡量少的次數將某乙個變數取出來。關於結構體內存對齊的方式,只需要把握兩點即可 上面說了,編譯預設對齊方式是4位元...

位元組對齊 pragma pack

這是給編譯器用的引數設定,有關結構體位元組對齊方式設定,pragma pack是指定資料在記憶體中的對齊方式。pragma pack n 作用 c編譯器將按照n個位元組對齊。pragma pack 作用 取消自定義位元組對齊方式。pragma pack push,1 作用 是指把原來對齊方式設定壓棧...

資料在記憶體中對齊方式 pragma pack

在程式中,有的時候我們定義結構體的時候,要用 pragma pack push,1 pragma pack pop 類似 將結構體包起來。一般形式如下 pragma pack push,1 struct a pragma pack pop 這麼做有什麼目的呢?注 下列內容來自網路。2 pragma ...