轉自:http://www.cnblogs.com/JensenCat/p/4770171.htmlhtml
這裏是頭文件結構的定義:ios
一個非字節對齊結構體_tagTest2測試
一個字節對齊_tagTest3spa
(使用#pragma pack(push,1)來使字節以1個來對齊 , 使用#pragma pack(pop)來還原默認)code
1 #pragma once 2 3 4 struct _tagTest1 5 { 6 }; 7 8 //非字節對齊的結果 9 struct _tagTest2 10 { 11 int n1; 12 char ch1; 13 float f1; 14 char szName[21]; 15 _tagTest1* pTag; 16 }; 17 18 #pragma pack(push,1) 19 //_tagTest3和2是同樣的結構,字節對齊後的結果 20 struct _tagTest3 21 { 22 int n1; 23 char ch1; 24 float f1; 25 char szName[21]; 26 _tagTest1* pTag; 27 }; 28 29 #pragma pack(pop)
這裏是實驗代碼:註釋處寫了分析,結果也入分析所料htm
1 #include "msgdef.h" 2 #include <Windows.h> 3 #include <iostream> 4 using namespace std; 5 6 void main() 7 { 8 /* 9 非字節對齊下,當前最大的空間是4個字節,全部結構都會向4個字節對齊... 10 int n1; 4 11 char ch1; 4 註解:1不是4的倍數..將擴張到4 12 float f1; 4 13 char szName[21]; 24 註解:21不是4的倍數..將擴張到24 14 _tagTest1* pTag; 4 15 總和爲:40 16 */ 17 _tagTest2 k2; 18 cout<<"size of _tagTest2: "<<sizeof(k2)<<endl; 19 //看看內存模型 20 k2.n1 = 1; 21 k2.ch1 = 1; 22 k2.f1 = 1.0f; 23 memset(k2.szName , 1 , sizeof(k2.szName)); 24 k2.pTag = (_tagTest1*)&k2.n1; //此處測試用,別糾結 25 26 27 /* 28 字節對齊下, 29 int n1; 4 30 char ch1; 1 31 float f1; 4 32 char szName[21]; 21 33 _tagTest1* pTag; 4 34 總和爲:34 35 */ 36 _tagTest3 k3; 37 cout<<"size of _tagTest3: "<<sizeof(k3)<<endl; 38 //看看內存模型 39 k3.n1 = 1; 40 k3.ch1 = 1; 41 k3.f1 = 1.0f; 42 memset(k3.szName , 1 , sizeof(k3.szName)); 43 k3.pTag = (_tagTest1*)&k3.n1; //此處測試用,別糾結 44 45 system("pause"); 46 }
實驗結果輸出:如分析所說的同樣blog
這時候問題來了,那麼字節不對齊時在內存是怎樣的呢...下面是字節不對齊時的內存截圖內存
下面的順序清楚的對應,其中字節對齊的空位在內存裏面補了cc,這個爲何本人沒有深究,其餘變量一目瞭然了,io
至於浮點數的內存模型爲何是這樣,能夠度娘一下,不少人分析了浮點數float的內存模型。class
----------------------------------------------------------------------------------------------------------------------------
----------------------------邪惡的分割線------------------------------------------------------------------------------------
2.0版本:
鑑於上面有些地方不夠清晰...如今再列出幾個例子...例子來自網上摘下...
1.在不對齊的狀況下,擁有相同變量的結構最後得出的size也是不同的..
//定義兩個結構,下面描述一下內存存放地址 struct A { //假設內存地址從0開始... int a; //0-3 char b; //4 short c;//6-7 } //因爲0-7的相加的結果爲8...爲自對齊4的倍數... //因此結果:sizeof(A) = 8 // struct B { //假設內存地址從0開始... char a;//0 int b; //4-7 short c;//8-10 } //因爲0-10的相加的結果爲11...不爲自對齊4的倍數...補齊後爲12 //因此結果:sizeof(B) = 12
2.再來使用Pragma手工更改了字節對齊值的狀況,先看看Struct C的定義:
#pragma pack(2) struct C { //假設從0開始 char a;//0 int b;//2-5 short c;//6-7 }; sizeof(C)的答案爲8
Struct C的分析摘自網友總結:
step 1: 肯定結構體C對齊值:選擇成員中最大的對齊值,即int a,對齊值爲4
step 2: 肯定手工指定對齊值,使用手工指定的值:2
step 3: char a 的有效地址值=min(1,2),(由於0x0000%2=0),這樣a的地址就是0x0000
step 4: int b 的有效對齊值=min(4,2),地址依次從0x0002~0x0005 (由於Ox0002%2=0)開始,分配4個字節,目前地址段分配狀況就是:0x0000~0x0005
step 5: short c 的有效對齊值=min(2,2),因爲要求考慮到對齊的狀況,從0x0006(由於0x0006%2=0)開始,分配2個字節的地址0x0006~0x0007
目前爲止,地址段的分配狀況就是:0x0000~0x0007共8個字節,同時也保證了Struct C的對齊狀況(2字節對齊,pragma(2)),sizeof(C)=8
結論:
最後的最後補多一個混合的例子:
1 struct tagS1 2 { 3 //假設地址從0開始,這裏最長的類型爲_unT1,長度爲8... 4 //變量的首地址爲地址模sizeof(變量類型)結果爲0的地址開始 5 char a;//0 (0模1==0,因此從0開始) 6 int n;//4-7 (2和3模4不等於0,從4開始) 7 _unT1 t1;//8-15(8模8等於0,從8開始) 8 long l;//16-19(16模4等於0,從16開始) 9 char sz[22];//20-41(20模1等於0,從20開始) 10 }; 11 //因爲0-41的長度爲42,42不爲8的倍數,因此補長爲8的倍數,結果爲48