今天看面試寶典時遇到一個問題如下:
class A{
public:
double d;
float a;
int b;
char c;
A();
~A();
};
int mian()
{
cout<<sizeof(A);
}
以我對數據對齊的理解,d爲8個字節,那麼a,b,c均佔8個字節,但是實際上是24個字節(在vc中測試的結果)。後來我打印出它的地址發現,&A.d=0x0012ff58,&A.a=0x0012ff60,&A.b=0x0012ff64,&A.c=0x0012ff68;
由此知道,d佔八個字節,而float和int各佔四個字節,但是依據數據對齊原理:對於n字節的元素(n=2,4,8,。。。),它的首地址能被n整除才能獲得最好的性能。所以c只需一個字節即可,但是實際上編譯器爲A.c申請了8個字節。測試如下:
int main()
{
int test1;
A testA;
int test2;
printf("%08x %08x %08x %08x %08x %08x\n",&test2,&AA.d,&AA.a,&AA.b,&AA.c,&test1);
}
執行的結果爲:0x0012ff54 0x0012ff58 0x0012ff60 0x0012ff64 0x0012ff68 0x0012ff70
由於test1、testA、test2等都是局部變量,均在棧中分配,且test1的地址高,而testA的地址較低,以此類推
從結果可以看出,testA的起始地址是0x0012ff58,結束地址爲0x0012ff70,說明結構體A中的c分配了8個字節的空間。
結論:在編譯器爲變量分配內存時,會依據類型大小最大的變量來對齊(如double),如果有比着小的數據類型並且可以遵循數據對齊原理(上面所述)就是說下一個變量的開始地址必須是它本身的n倍才行,可以按找它自己的大小來分配(如int、float加起來真好是8個字節和double對齊),最後雖然c只是佔用一個字節,但是在此結構體中需要和double對齊,所以也佔據8個字節的空間,如果在c的後面加上多個char類型的變量(別超過7個),整個結構體的大小不會變,還是24,或者加入一個int型的變量,整個結構體的大小還是24。有了這些知識後看下面一個例題:
class B{
public:
bool m_bTemp;
int m_nTmep;
bool m_bTemp2;
};
class C{
public:
int m_nTmep;
bool m_bTemp;
bool m_bTmep2;
}
cout<<sizeof(B)<<endl;
cout<<sizeof(C)<<endl;
執行結果爲:
12
8
在內存中的佈局爲:
類B:
| bool l ------ | ------ | ------ |
| --------------int-------------- |
| bool | bool | ------ | ------ |
類C:
| --------------int-------------- |
| bool | bool | ------ | ------ |
另外需要注意的是:char *str=“dafddsfasdfasdf”;
char str2[]="dfadfasdfasdf";
sizeof(str)=4;//僅僅是一個指針大小
sizeof(str2)=14;//包含\0的字符串大小