C++中結構體的對齊方式
在面試中,常會考到結構體的對齊方式,因此對其進行總結。
1、在沒有#pragma pack巨集的情況下
-
struct sA{
-
double d1;
-
int i1;
-
double d2;
-
char c1;
-
};
原則1:每個成員按型別的大小對齊,即相對於結構體地址的成員地址能被型別大小整除.並且結構體的大小(sizeof(A))必須為成員所含型別中最大值(sizeof(double))的整數倍,不夠就補空位元組.
例1:
例如用結構體定義物件A,其第一個成員d1的型別為double,大小為8位元組,它的地址(也是A的地址)就需要能被4整除,這主要是因為為A申請記憶體時,其地址由其成員中所含的最大型別單獨申請記憶體的規則決定(A中最大型別為double),int和double型別在單獨申請記憶體時,其地址為4的整數倍。第二個成員i1的型別為int,大小為4位元組,它相對於結構體A地址(00BDF7EC)的成員地址(8)能被4整除,不需要補充空白位元組。第三個成員d2的型別為double,大小為8位元組,它相對於結構體A地址(00BDF7EC)的成員地址(12)不能被8整除,需要補充4個空白位元組。第四個成員c1的型別為char,大小為1位元組,它相對於結構體A地址(00BDF7EC)的成員地址(16)能被1整除,不需要補充空白位元組。
原則2:結構體作為成員,型別大小按其成員所含最大型別計算。
-
struct sB{
-
char c1;
-
sA sA1;
-
};
例2:struct sB裡存有struct sA,其結構體成員sA1的型別大小按8位元組計算
原則3:結構體的總大小,為其成員中所含最大型別的整數倍。在例1中即為成員d1型別(double,8)的整數倍。而在例二中即為成員sA1型別(8)的整數倍。
2、在有#pragma pack巨集的情況下
(1)#pragma pack(1),例1和例2的情況如下
可以看到其成員均按1作為其型別大小進行對齊,結構體的總大小也為1的整數倍。
(2)#pragma pack(2),例1和例2的情況如下
可以看到其成員均按2作為其型別大小進行對齊,結構體的總大小也為2的整數倍。
(3)#pragma pack(4),例1和例2的情況如下
可以看到其成員均按4作為其型別大小進行對齊,結構體的總大小也為4的整數倍。
附上程式碼
#include<stdio.h>
#include<iostream>
using namespace std;
#pragma pack(2)
struct sA{
double d1;
int i1;
double d2;
char c1;
};
struct sB{
char c1;
sA sA1;
};
int main()
{
sA A;
sB B;
cout << "A的地址:" << &A << endl
<< "A.d1的地址:" << &A.d1 << endl
<< "A.i1的地址:" << &A.i1 << endl
<< "A.d2的地址:" << &A.d2 << endl
<< "A.c1的地址:" <<(void*)&A.c1 << endl
<< "A的大小:" << sizeof(A) << endl;
cout << "B的地址:" << &B << endl
<< "B.c1的地址:" <<(void*) &B.c1 << endl
<< "B.sA1的地址:" << &B.sA1 << endl
<< "B的大小:" << sizeof(B) << endl;
while (1);
return 0;
}