sizeof()功能:計算資料空間的位元組數
1.與strlen()比較
strlen()計算字元數組的字元數,以"/0"為結束判斷,不計算為'/0'的數組元素。
而sizeof計算資料(包括數組、變量、類型、結構體等)所占記憶體空間,用位元組數表示。
2.指針與靜态數組的sizeof操作
指針均可看為變量類型的一種。所有指針變量的sizeof 操作結果均為4。
注意:int *p; sizeof(p)=4;
但sizeof(*p)相當于sizeof(int);
對于靜态數組,sizeof可直接計算數組大小;
例:int a[10];char b[]="hello";
sizeof(a)等于4*10=40;
sizeof(b)等于6;
注意:數組做型參時,數組名稱當作指針使用!!
void fun(char p[])
{
sizeof(p) // 等于4
}
經典問題:
double* (*a)[3][6];
cout<<sizeof(a)<<endl; // 4 a為指針
cout<<sizeof(*a)<<endl; // 72 *a為一個有3*6個指針元素的數組
cout<<sizeof(**a)<<endl; // 24 **a為數組一維的6個指針
cout<<sizeof(***a)<<endl; // 4 ***a為一維的第一個指針
cout<<sizeof(****a)<<endl; // 8 ****a為一個double變量
問題解析:
a是一個很奇怪的定義, 他表示一個指向double*[3][6]類型數組的指針。 既然是指針, 是以sizeof(a)就是4。 既然a是執行double*[3][6]類型的指針, *a就表示一個double*[3][6]的多元數組類型, 是以sizeof(*a) = 3*6*sizeof(double*) = 72。 同樣的, **a表示一個double*[6]類型的數組, 是以sizeof(**a) = 6*sizeof (double*) = 24。 ***a就表示其中的一個元素,也就是double*了,是以sizeof(***a) = 4。至于 ****a,就是一個double了,是以sizeof(****a) = sizeof(double)=8。
3.格式的寫法
sizeof操作符,對變量或對象可以不加括号,但若是類型,須加括号。
4.使用sizeof時string的注意事項
string s="hello";
sizeof(s)等于string類的大小,sizeof(s.c_str())得到的是與字元串長度。
5.union 與struct的空間計算
總體上遵循兩個原則:
(1)整體空間是 占用空間最大的成員(的類型)所占位元組數的整倍數
(2)資料對齊原則----記憶體按結構成員的先後順序排列,當排到該成員變量時,其前面已擺放的空間大小必須是該成員類型大小的整倍數,如果不夠則補齊,以此向後類推。。。。。
注意:數組按照單個變量一個一個的擺放,而不是看成整體。如果成員中有自定義的類、結構體,也要注意數組問題。
例:[引用其他文章的内容]
因為對齊問題使結構體的sizeof變得比較複雜,看下面的例子:(預設對齊方式下)
struct s1
{
char a;
double b;
int c;
char d;
};
struct s2
{
char a;
char b;
int c;
double d;
};
cout<<sizeof(s1)<<endl; // 24
cout<<sizeof(s2)<<endl; // 16
同樣是兩個char類型,一個int類型,一個double類型,但是因為對齊問題,導緻他們的大小不同。計算結構體大小可以采用元素擺放法,我舉例子說明一下:首先,CPU判斷結構體的對界,根據上一節的結論,s1和s2的對界都取最大的元素類型,也就是double類型的對界8。然後開始擺放每個元素。
對于s1,首先把a放到8的對界,假定是0,此時下一個空閑的位址是1,但是下一個元素d是double類型,要放到8的對界上,離1最接近的位址是8了,是以d被放在了8,此時下一個空閑位址變成了16,下一個元素c的對界是4,16可以滿足,是以c放在了16,此時下一個空閑位址變成了20,下一個元素d需要對界1,也正好落在對界上,是以d放在了20,結構體在位址21處結束。由于s1的大小需要是8的倍數,是以21-23的空間被保留,s1的大小變成了24。
對于s2,首先把a放到8的對界,假定是0,此時下一個空閑位址是1,下一個元素的對界也是1,是以b擺放在1,下一個空閑位址變成了2;下一個元素c的對界是4,是以取離2最近的位址4擺放c,下一個空閑位址變成了8,下一個元素d的對界是8,是以d擺放在8,所有元素擺放完畢,結構體在15處結束,占用總空間為16,正好是8的倍數。
這裡有個陷阱,對于結構體中的結構體成員,不要認為它的對齊方式就是他的大小,看下面的例子:
struct s1
{
char a[8];
};
struct s2
{
double d;
};
struct s3
{
s1 s;
char a;
};
struct s4
{
s2 s;
char a;
};
cout<<sizeof(s1)<<endl; // 8
cout<<sizeof(s2)<<endl; // 8
cout<<sizeof(s3)<<endl; // 9
cout<<sizeof(s4)<<endl; // 16;
s1和s2大小雖然都是8,但是s1的對齊方式是1,s2是8(double),是以在s3和s4中才有這樣的差異。
是以,在自己定義結構體的時候,如果空間緊張的話,最好考慮對齊因素來排列結構體裡的元素。
補充:不要讓double幹擾你的位域
在結構體和類中,可以使用位域來規定某個成員所能占用的空間,是以使用位域能在一定程度上節省結構體占用的空間。不過考慮下面的代碼:
struct s1
{
int i: 8;
int j: 4;
double b;
int a:3;
};
struct s2
{
int i;
int j;
double b;
int a;
};
struct s3
{
int i;
int j;
int a;
double b;
};
struct s4
{
int i: 8;
int j: 4;
int a:3;
double b;
};
cout<<sizeof(s1)<<endl; // 24
cout<<sizeof(s2)<<endl; // 24
cout<<sizeof(s3)<<endl; // 24
cout<<sizeof(s4)<<endl; // 16
可以看到,有double存在會幹涉到位域(sizeof的算法參考上一節),是以使用位域的的時候,最好把float類型和double類型放在程式的開始或者最後。
相關資料類型位元組數:
sizeof int:4
sizeof short:2
sizeof long:4
sizeof float:4
sizeof double:8
sizeof char:1
sizeof p:4
sizeof WORD:2
sizeof DWORD:4