記憶體對齊之學會計算結果

2021-08-19 20:58:11 字數 2724 閱讀 5324

一、記憶體對齊的原因

大部分的參考資料都是如是說的:

1、平台原因(移植原因):不是所有的硬體平台都能訪問任意位址上的任意資料 的;某些硬體平台只能在某些位址處取某些特定型別的資料,否則丟擲硬體異常。

2、效能原因:資料結構(尤其是棧)應該盡可能地在自然邊界上對齊。 原因在於,為了訪問未對齊的記憶體,處理器需要作兩次記憶體訪問;而對齊的記憶體訪問僅需要一次訪問。

二、對齊規則

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

規則:

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

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

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

4.、巢狀結構體的首位址遵循整體對齊

5、結構體中的陣列就當拆分成乙個個元素對齊

總結:

if**指定了pack係數

整體對齊係數 = min((max(結構體中所有型別資料), pack)

else

整體對齊係數 = min((max(結構體中所有型別資料))

end

下面通過幾個例子加深理解。todo:下面的例子都是預設在4位元組對齊,vs2013執行的,括號代表是填充的位元組

struct test1 ;

上述沒有指定對齊引數,整體對齊係數(all) = min(max(4,1,2)) = 4

1.資料成員對齊:

a ,4 = all,0%4=0,佔據[0,3]

b,1 < all,4%1=0,佔據[4]

c,2 < all,5%2~=0,所以[5]被填充,c佔據[6,7]

d,1 < all,8%2 = 0,

總大小 = [0,8]=9

但是別忘了:

2.結構自身對齊,9%all ~= 0,最後總大小等於12,因為12%4 = 0

實際記憶體分布:a[0,3],b[4,5],c[6,7],d[8,11]

現在指定記憶體對齊

# pragma pack(1)

struct test1 ;

# pragma pack()

整體對齊係數(all) = min(max(4,1,2),1) = 1

1.資料成員對齊:

a,4 > all,0%all=0,佔據[0,3]

b,1 = all,4%1=0,佔據[4],

c,2 > all,5%1=0,佔據[5,6],

d,1 = all,7%1=0,佔據[7]

2.結構自身對齊,8%all = 0

總大小等於8

# pragma pack(2)

struct test1 ;

# pragma pack()

整體對齊係數(all) = min(max(4,1,2),2) = 2

1.資料成員對齊:

a,4 > all,0%all=0,佔據[0,3]

b,1 < all,4%1=0,佔據[4],

c,2 = all,5%all~=0,被填充5,佔據[6,7]

d,1 < all,8%1=0,佔據[8]

2.結構自身對齊,9%all ~= 0,總大小等於10,因為10%all = 0

實際記憶體分布:a[0,3],b[4,5],c[6,7],d[8,9]

巢狀結構體的情況

struct test1

inside;

int f;

char* g[6];

}; 整體對齊係數(all) = min(max(4,1,2,8)) = 8

1.資料成員對齊:

a,1 < all,0%1=0,佔據[0]

b,4 < all,1%4~=0,填充[1,2,3],佔據4,5,6,7

inside的內部結構體的首位址8%all = 0,滿足規則4

inside.c,1 < all,8%1=0,佔據[8,9,10,11,12]

inside.d,1 < all,13%1=0,佔據[13]

inside.e,8 = all,14%8 ~= 0,填充[14,15],佔據[16,23]

f,4 < 24, 24%4=0,佔據[24,27]

g,4 < all,28%4 = 0,佔據4*6 ,就是[28,51]

2.結構自身對齊

52%all ~=0,所以總大小等於56,因為56%all = 0

# pragma pack(1) 這種情況就不寫過程了,all = min(max(4,1,2,8),1) = 1

總大小等於所有長度之和 1 + 4 + 5 + 1+ 8 + 4 + 4*6 = 47

#pragma pack(2) 的情況,all = min(max(4,1,2,8),2) = 2

總大小等於 2(t填充1)+ 4 + 5 + 1 + 8 + 4 + 4*6 = 48

參考

記憶體對齊(計算結構體大小)方法

struct stu1 結構體大小等於最後乙個成員的偏移量加上最後乙個成員的大小。第乙個成員i的偏移量為0。第二個成員c的偏移量是第乙個成員的偏移量加上第乙個成員的大小 0 4 其值為4 第三個成員j的偏移量是第二個成員的偏移量加上第二個成員的大小 4 1 其值為5。由於儲存變數時位址對齊的要求,編...

計算機記憶體中的對齊

現代計算機中記憶體空間都是按照byte劃分的,從理論上講似乎對任何型別的變數的訪問可以從任何位址開始,但實際情況是在訪問特定變數的時候經常在特定的記憶體位址訪問,這就需要各型別資料按照一定的規則在空間上排列,而不是順序的乙個接乙個的排放,這就是對齊。對齊的作用和原因 各個硬體平台對儲存空間的處理上有...

記憶體對齊之結構體大小的計算

結構體變數的位址受到記憶體對齊規則的影響,使得結構體成員並不是在記憶體中 緊挨 著的。可以參照如下結構體 10執行結果如下 最終,我用excel 的形式,做出如下的結構體成員的記憶體分配位置,如下圖黃色為實際存在資料的記憶體單元,白色空格為適應記憶體對齊而進行的偏移量。需要注意系統預設是4位元組對齊...