記憶體對齊 記憶體對齊規則解釋 記憶體對齊原理

2021-10-04 12:23:10 字數 3098 閱讀 7986

一、記憶體對齊的原因

我們都知道計算機是以位元組(byte)為單位劃分的,理論上來說cpu是可以訪問任一編號的位元組資料的,我們又知道cpu的定址其實是通過位址匯流排來訪問記憶體的,cpu又分為32位和64位,在32位的cpu一次可以處理4個位元組(byte)的資料,那麼cpu實際定址的步長就是4個位元組,也就是只對編號是4的倍數的記憶體位址進行定址。同理64位的cpu的定址步長是8位元組,只對編號是8的倍數的記憶體位址進行定址,如下圖所示是64位cpu的定址示意圖:

這樣做可以實現最快速的方式定址且不會遺漏乙個位元組,也不會重複定址。

那麼對於程式而言,乙個變數的資料儲存範圍是在乙個定址步長範圍內的話,這樣一次定址就可以讀取到變數的值,如果是超出了步長範圍內的資料儲存,就需要讀取兩次定址再進行資料的拼接,效率明顯降低了。例如乙個double型別的資料在記憶體中佔據8個位元組,如果位址是8,那麼好辦,一次定址就可以了,如果是20呢,那就需要進行兩次定址了。這樣就產生了資料對齊的規則,也就是將資料盡量的儲存在乙個步長內,避免跨步長的儲存,這就是記憶體對齊。在32位編譯環境下預設4位元組對齊,在64位編譯環境下預設8位元組對齊。

檢視自己電腦是多少位作業系統

終端下輸入:uname -a 回車

x86_64 表示系統為64位

i686 表示系統32位的

二、對齊規則

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

2:資料成員為結構體:如果結構體的資料成員還為結構體,則該資料成員的「自身長度」為其內部最大元素的大小。(struct a 裡存有 struct b,b 裡有char,int,double等元素,那 b 「自身長度」為 8)

3:結構體的整體對齊規則:在資料成員按照 #1 完成各自對齊之後,結構體本身也要進行對齊。對齊會將結構體的大小增加為 #pragma pack 指定的數值和結構體最大資料成員長度中較小那個的整數倍。

(看不懂沒關係,因為我也沒看懂,也是列印之後才明白)

三、例項

typedef

struct test1 test1;

//資料成員

intmain

(int argc,

const

char

* ar**)

結果:

32

0x7ffeefbff568

0x7ffeefbff56c

0x7ffeefbff570

0x7ffeefbff578

以首位址0x7ffeefbff568為offset=0,

0x68=104,

0x6c=108,

0x70=112,

0x78=120,

0x7ffeefbff56c相對於0x7ffeefbff568便宜了4,

0x7ffeefbff570相對於0x7ffeefbff568便宜了8,

0x7ffeefbff578相對於0x7ffeefbff568偏移了16,符合規律

上面int b正好偏移4,double c正好偏移8,比較湊巧,如果char a[5]呢,使位址正好措開,此時int b應該是[8…13],double c應該是[16…23], char d[11]應該是[24…34],34不是最大double c的整數倍,補齊到最小倍數40,所以結構體的大小應該是40.

40

0x7ffeefbff560

0x7ffeefbff568

0x7ffeefbff570

0x7ffeefbff578

program ended with exit code:

0

在結構體struct test1中新增乙個結構體test2,看下結果:

typedef

struct test2 test2;

typedef

struct test1 test1;

//資料成員

//此時:

// char a[13];//1 [40...52]

// double b;//8 [56...63]

// int c[11];//4 [64...107]

// float d;//4 [107...111]

intmain

(int argc,

const

char

* ar**)

結果:

72

112program ended with exit code:

0

把test2中的double b登出了,看下結果:

typedef

struct test2 test2;

typedef

struct test1 test1;

//資料成員

intmain

(int argc,

const

char

* ar**)

64

104program ended with exit code:

0

四、更改預設對齊係數

#pragma pack(2)

//1、2、4、8、16,以2為例

typedef

struct test2 test2;

intmain

(int argc,

const

char

* ar**)

結果:

62

program ended with exit code:

0

參考:

記憶體對齊規則

1 平台原因 移植原因 不是所有的硬體平台都能訪問任意位址上的任意資料的 某些硬 件平台只能在某些位址處取某些特定型別的資料,否則丟擲硬體異常。2 效能原因 資料結構 尤其是棧 應該盡可能地在自然邊界上對齊。原因在於,為了訪問 未對齊的記憶體,處理器需要作兩次記憶體訪問 而對齊的記憶體訪問僅需要一次...

記憶體對齊規則

隔了很久,搞忘了對齊的規則,現在重新複習了下,記下來謹防以後又忘記。1 可以根據 pragma pack 設定對齊係數,且叫為n 2 結構體中,對比每個成員變數自身的大小和n的大小。取小的個為標準,把這個小的叫a吧,稱為按a對齊 3 每個變變數的起始位址需要為a的整數倍,不是整數倍的則補齊。4 最後...

記憶體對齊詳細解釋

記憶體對齊詳細解釋 1 分析說明 輸出結果 sizeof structtest t 10 兩個編譯器輸出一致 分析過程 pragmapack 2 structtest t pragmapack 成員總大小 9總體對齊係數 min max int,short,char 2 2 總體大小 size 成員...