一、記憶體對齊的原因
大部分的參考資料都是如是說的:
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位元組對齊...