struct:
struct MyStruct
{
double a;
char b;
int c;
};
sizeof(MyStrut)=?????
很多朋友會認爲結果是:8(sizeof(a))+1(sizeof(b))+4(sizeof(c))=13
但是當我們在vs上運行輸出的結果是 16,這是爲什麼呢?
這是編譯器爲了提高cup的存儲速度對一些起始地址進行了"對齊"處理.
雖然對齊原則和編譯器有關聯但是以下的原則是必須遵守的:
結構體變量的首地址能夠被其最寬基本類型成員的大小整除。
結構體每個成員相對於結構體首地址偏移量都是成員大小的整數倍,不夠就進行字節填充。
結構體的總大小爲最寬數據成員的整數倍,不夠就字節填充。
所以再將目光轉向MyStruct:
第一個變量a首地址偏移量爲0,是sizeof(a)=8的整數倍,所以佔用8+0=8個字節。
第二個變量b首地址偏移量爲8,是sizeof(b)=1的整數倍,所以佔用1個字節,將b放在偏移量爲8的地方。
第三個變量c首地址偏移量8+1=9,不是sizeof(c)=4的整數倍所以進行字節填充9+3=12(離9最近的4的倍數),變量c佔用4個字節。
綜上:8+1+3+4=16 16是最大數據類型double=8的整數倍(不用補充字節),所以最後結果是16.
如果我們將MyStruct的數據位置換一下
struct MyStruct
{
char a;
double b;
int c;
};
那麼sizeof(MyStruct)的結果會是
sizeof(a)=1;
sizeof(b)=8;
sizeof(c)=4;
(1+7+8+4)=20;(包含了填充字節);
但是20不是8的整數倍所以填充字節20+4=24(離20最近的8的整數倍)
當然我們也可以用#pragam pack(n)來終結這種喪心病狂的對齊方式
eg:
#pragam pack(push)//保存對齊狀態
#pragam pack(4)(以4字節方式對齊)
struct Test
{
char a;
double b;
int c;
};
#pragam pack(pop)
原則:
若n>變量字節 採用默認對齊方式
若n<變量字節 採用n的倍數對齊方式
若n>所有變量(單個)的字節數,那麼總大小爲最大變量的整數倍,否則爲n的整數倍
sizeof(Test)=1+3+8+4=13 補齊3個字節=16;
若把#pragam pack(4)改爲#pragam pack(16)
sizeof(Test)=1+7+8+4+4=24;
union:
union Test
{
int a;
double b;
char c;
};
sizeof(Test)
sizeof(a)=4;
sizeof(b)=8;
sizeof(c)=1;
sizeof(Test)以最長爲所有字節 8 又因爲8是8的倍數所以最後爲8(union以單個最長字節對齊)
class:
一、個空類
class A
{
};
求sizeof的結果是1,因爲即使是沒有成員之類的,一個類存在,至少都要給他一個空間,不然就沒有存在的意義了。
二、簡單的類
class A
{
int a;
virtual fun();
}
這個也好求,就是sizeof(A.a)+4(指向虛表的指針)
三、子類普通繼承、父類中不含虛函數
class A
{
int a;
}
class B:public A
{
int b;
virtual fun();
}
sizeof(B)=sizeof(A)+sizeof(B.b)+4(指向虛表指針)
四、子類普通繼承、父類含虛函數
class A
{
int a;
virtual fun1();
}
class B:public A
{
int b;
virtual fun();
}
sizeof(B)=sizeof(A)-4(sizeof(A)中有一個指向虛表的指針)+sizeof(B.b)+4(指向虛表指針)
因爲普通繼承,子類和父類的虛函數存放在同一個虛表中,所以,只需要存一個指向續表的指針即可;
五、子類虛繼承、父類不含虛函數
class A
{
int a;
}
class B:virtual public A
{
int b;
virtual fun();
}
sizeof(B)=sizeof(A)+4(指示父類存放空間的起始偏移量)+sizeof(B.b)+4(指向B的虛表的指針)
六、子類虛繼承、父類含虛函數
class A
{
int a;
virtual fun1();
}
class B:virtual public A
{
int b;
virtual fun();
}
sizeof(B)=sizeof(A)+4(指示父類存放空間的起始偏移量)+sizeof(B.b)+4(指向B的虛表的指針)
虛繼承時,父類和子類的虛函數表分開放,所以,分別存儲兩個指向對應續表的指針,因而不用減去sizeof(A)中續表指針的大小。