C++結構體字節對齊(c++常見問題開篇)


本站文章均為Jensen抹茶喵原創,轉載務必在明顯處注明:
轉載自【博客園】 原文鏈接:http://www.cnblogs.com/JensenCat/p/4770171.html

 

1.0版本:

這里是頭文件結構的定義:

一個非字節對齊結構體_tagTest2

一個字節對齊_tagTest3

(使用#pragma pack(push,1)來使字節以1個來對齊 , 使用#pragma pack(pop)來還原默認)

 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) 

 

這里是實驗代碼:注釋處寫了分析,結果也入分析所料

 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 }

實驗結果輸出:如分析所說的一樣

這時候問題來了,那么字節不對齊時在內存是怎樣的呢...下面是字節不對齊時的內存截圖

下面的順序清楚的對應,其中字節對齊的空位在內存里面補了cc,這個為什么本人沒有深究,其他變量一目了然了,

至於浮點數的內存模型為什么是這樣,可以度娘一下,很多人分析了浮點數float的內存模型。

 

----------------------------------------------------------------------------------------------------------------------------

----------------------------邪惡的分割線------------------------------------------------------------------------------------

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

 

結論:

 

 

最后的最后補多一個混合的例子:

struct tagS1
{
    //假設地址從0開始,這里最長的類型為_unT1,長度為8...
    //變量的首地址為地址模sizeof(變量類型)結果為0的地址開始
    char a;//0 (0模1==0,所以從0開始)
    int n;//4-7 (2和3模4不等於0,從4開始)
    _unT1 t1;//8-15(8模8等於0,從8開始)
    long l;//16-19(16模4等於0,從16開始)
    char sz[22];//20-41(20模1等於0,從20開始)
};
//由於0-41的長度為42,42不為8的倍數,所以補長為8的倍數,結果為48

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM