關鍵字sizeof的作用是返回對象或類型占用的內存字節數,返回值是size_t。
基本數據類型占用的字節數:(32位系統)
char 1字節
bool 1字節
short 2字節
int 4字節
long 4字節
float 4字節
double 8字節
對sizeof結果的一個重要影響因素是字節對齊。首先看一個公式:有效對齊值=min(自身對齊值,設置對齊值)。
自身對齊值是一個數據類型自身所占字節數,
例子:
int a; //自身對齊值是4 char c; //自身對齊值是1 double d; //自身對齊值是8 //對於結構體,自身對齊值是其內置數據類型中對齊值最大的值 struct s1{ int q; //4 bool e; //1 char w; //1 };// 最大的是int q,所以自身對齊值是4 struct s2{ int q; //4 bool e; //1 double r; //8 };// 最大的是double r,所以自身對齊值是8
設置對齊值是編譯器默認的對齊值,筆者用的是vs2013,默認對齊值是4字節,可以Project--->Properties--->Configuration Properties--->C\C++--->Code Generation
--->Struct Member Alignment中設置,也可以通過宏#pragma pack(n)來設置,n為要設置的對齊字節。
有效對齊值是對象或類型的自身對齊值和設置對齊值中較小的一個,也是實際真正的對齊值。
在上面的例子上加點改動後:
#pragma pack(4) //設置對齊值為4 struct s1{ int q; bool e; char w; }; //s1的自身對齊值是4,所以s1的有效對齊值=min(4,4)=4 #pragma pack(2) //設置對齊值為2 struct s2{ int q; bool e; double r; }; //s2的自身對齊值是8,所以s2的有效對齊值=min(8,2)=2
知道了有效對齊值就可以輕松地計算sizeof了。
一、基本數據類型的sizeof
sizeof(int)=4
sizeof(double)=8
......
二、結構體的sizeof
#pragma pack(4) struct s1{ int a; char b; }; //有效對齊值是4 sizeof(s1)=8 //int a占4字節,儲存在0x00--0x03,char b占1字節,儲存在0x04,因為有效對齊值是4,所以char b後面的0x05--0x07補齊對齊,一共占用8字節 //把s1稍作改動 struct s1{ char b; int a; }; //有效對齊值是4 sizeof(s1)=8 //答案一樣,但是內部儲存情況變了。char b占1字節,儲存在0x00,int a占4字節,因為有效對齊值是4,0x01---0x03只剩3字節的內存,小於int a所需的字節數,所以新分配一段4字節(有效對齊值)內存,最終int a儲存在0x04---0x07 //再看一個例子 struct s2 { char a; short b; double c; char d; }; //有效對齊值是4 sizeof(s2)=16 //char a占1字節,儲存在0x00;short b占2字節,由於有效對齊值是4,第一段內存剩余3字節0x01---0x03,大於short b所需,所以short b儲存在0x02---0x03(注意:儲存首地址必須是成員大小的整數倍,所以0x01空出);double c占8字節,大於有效對齊值,所以分配兩段內存0x04---0x0B用於儲存double c;char d占1字節,儲存在0x0C,按有效對齊值4字節對齊,最後的0x0D---0x0F補齊對齊。一共16字節。
三、結構體中含有結構體類型的sizeof
結構體的自身對齊值是其內置類型中最大的一個。
例子:
#pragma pack(2) class A { public: int a; double s; }; //A的自身對齊值是double s的自身對齊值,為8 //但A的有效對齊值是min(8,2)=2,sizeof(A)=12 class B { public: char c; //自身對齊值1,占1字節 A b; //自身對齊值8,占sizeof(A)=12字節 }; //B的自身對齊值等於A的自身對齊值,為8 //B的有效對齊值=min(8,2)=2,按2字節對齊 sizeof(B)=14 //char c占1字節,儲存在0x00,0x01空出;A b占12字節。一共14字節。
四、結構體中含有虛函數的sizeof
帶有虛函數的結構體會有一個虛表指針,占4字節大小。
例子:
#pragma pack(4) Class A { public: int a; virtual int test(); }; sizeof(A)=8 //int a占4字節,虛表指針占4字節,一共8字節。 //注意:如果一個結構體有多個虛函數,也還是只有一個虛表指針,即多個虛函數共用一個虛表指針
對於繼承的情況,如果基類有虛函數,那麼這個虛表指針也會被繼承下來,即基類和派生類共用一個虛表指針。
例子:
#pragma pack(4) class A { public: int a; double s; virtual int test(); }; class B:public A { public: virtual int test_1(); //共用基類虛表指針 virtual int test_2(); //共用基類虛表指針 char c; }; sizeof(B)=20 //int a占4字節+double s占8字節+虛表指針占4字節+char c占1字節+3字節補齊對齊=20字節
五、聯合體的sizeof
聯合體中各成員共享內存,整個聯合體的sizeof就是每個成員sizeof的最大值。
例子:
union u { int a; double b; char c; bool d; }; sizeof(u)=sizeof(b)=8
六、含有static的結構體的sizeof
static和全局變量都是儲存在靜態存儲區,計算結構體的sizeof時只計算非static成員。
例子:
#pragma pack(4) class A { public: int a; double b; static int d; //不管他 }; sizeof(A)=12 //int a占4字節+double b占8字節=12
七、函數的sizeof
結果是函數返回類型的大小,所以不能對沒有返回值的函數求sizeof。
格式sizeof(函數名(實參表))
例子:
int A() { return 1; } sizeof(A())=sizeof(int)=4 char B(char b) { return b; } sizeof(B('b'))=sizeof(char)=1 void C() { } sizeof(C()) //error,因為沒有返回類型
有理解錯誤的地方希望各位大神指正啊!!感激不盡!