關鍵字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,因為沒有返回類型
有理解錯誤的地方希望各位大神指正啊!!感激不盡!