char:8位
short:16位
int:32位
long:32位
float:32位
double:64位
一、接下來先來看struct,結構體
請牢記以下3條原則:(在沒有#pragma pack宏的情況下)
1、數據成員對齊規則:結構體(struct)的數據成員,第一個數據成員放在offset爲0的地方,之後的每個數據成員存儲的起始位置要從該成員大小的整數倍開始(比如int在32位機子上爲4字節,所以要從4的整數倍地址開始存儲)。
2、結構體作爲成員:如果一個結構體裏同時包含結構體成員,則結構體成員要從其內部最大元素大小的整數倍地址開始存儲(如struct a裏有struct b,b裏有char,int ,double等元素,那麼b應該從8(即double類型的大小)的整數倍開始存儲)。
3、結構體的總大小:即sizeof的結果。在按之前的對齊原則計算出來的大小的基礎上,必須還得是其內部最大成員的整數倍,不足的要補齊(如struct裏最大爲double,現在計算得到的已經是11,則總大小爲16)。
具體例子:
- typedef struct bb
- {
- int id; //[0]....[3] 表示4字節
- double weight; //[8].....[15] 原則1
- float height; //[16]..[19],總長要爲8的整數倍,僅對齊之後總長爲[0]~[19]爲20,補齊[20]...[23] 原則3
- }BB;
<span style="font-size:18px;"><strong>typedef struct bb
{
int id; //[0]....[3] 表示4字節
double weight; //[8].....[15] 原則1
float height; //[16]..[19],總長要爲8的整數倍,僅對齊之後總長爲[0]~[19]爲20,補齊[20]...[23] 原則3
}BB;</strong></span>
- typedef struct aa
- {
- int id; //[0]...[3] 原則1
- double score; //[8]....[15]
- short grade; //[16],[17]
- BB b; //[24]......[47] 原則2(因爲BB內部最大成員爲double,即8的整數倍開始存儲)
- char name[2]; //[48][49]
- }AA;
<span style="font-size:18px;"><strong>typedef struct aa
{
int id; //[0]...[3] 原則1
double score; //[8]....[15]
short grade; //[16],[17]
BB b; //[24]......[47] 原則2(因爲BB內部最大成員爲double,即8的整數倍開始存儲)
char name[2]; //[48][49]
}AA; </strong></span>
<span style="font-size:18px;"><strong>int main()
{
cout<<sizeof(AA)<<" "<<sizeof(BB)<<endl;
return 0;
}</strong></span>
輸出結果爲56 24
以上結果是在沒有#pragma pack(n)宏的情況下,現在來講講關於#pragma pack(n)。
編譯器中提供了#pragma pack(n)來設定變量以n字節對齊方式。//n爲1、2、4、8、16...
n字節對齊就是說變量存放的起始地址的偏移量有兩種情況:第一、如果n大於等於該變量所佔用的字節數,那麼偏移量必須滿足默認的對齊方式,即該變量所佔用字節數的整數倍;第二、如果n小於該變量的類型所佔用的字節數,那麼偏移量爲n的倍數,不用滿足默認的對齊方式。
結構的總大小也有個約束條件,分下面兩種情況:如果n大於所有成員變量類型所佔用的字節數,那麼結構的總大小必須爲佔用空間最大的變量佔用的空間數的倍數;否則必須爲n的倍數。
所以在上面的代碼前加一句#pragma pack(1),
則代碼輸出爲bb:(0~3)+(4~11)+(12~15)=16;aa:(0~3)+(4~11)+(12~13)+(14~29)+(30~31)=32,也就是說,#pragma pack(1)就是沒有對齊規則。
再考慮#pragma pack(4),bb:(0~3)+(4~11)+(12~15)=16;aa:(0~1)+(4~11)+(12~13)+(16~31)+(32~35)=36
二、union共用體(聯合)
<span style="font-size:18px;"><strong>union foo
{
char s[10];
int i;
}</strong></span>
<span style="font-size:18px;"><strong>union mm{
char a;//元長度1 1
int b[5];//元長度4 20
double c;//元長度8 8
int d[3]; 12
};
</strong></span>
所以sizeof(mm)=8*3=24;<span style="font-size:18px;"><strong>struct inner
{
char c1;
double d;
char c2;
};
union data4
{
struct inner t1;
int i;
char c;
};
</strong></span>
由於data4共用體中有一個inner結構體,所以最大的基本數據類型爲double,因此以8字節對齊。共用體的存儲長度取決於t1,而t1長度爲24,因此sizeof(uniondata4)的值爲24.當在結構體中包含共用體時,共用體在結構體裏的對齊地址爲共用體本身內部所對齊位數,如下:
- typedef union{
- long i;
- int k[5];
- char c;
- }DATE;
- struct data{
- int cat;
- char cc;
- DATE cow;
- char a[6];
- };
<span style="font-size:18px;"><strong>typedef union{
long i;
int k[5];
char c;
}DATE;
struct data{
int cat;
char cc;
DATE cow;
char a[6];
};</strong></span>