C\C++ sizeof 陷阱

sizeof用來(lái)**求對(duì)象或者類(lèi)型的大小。**下面列出sizeof十個(gè)特性:摘自([http://www.cppblog.com/w57w57w57/archive/2011/08/09/152845.html](http://www.cppblog.com/w57w57w57/archive/2011/08/09/152845.html))
(0)sizeof是運(yùn)算符,不是函數(shù);
(1)sizeof不能求得void類(lèi)型的長(zhǎng)度;
(2)sizeof能求得void類(lèi)型的指針的長(zhǎng)度;
(3)sizeof能求得**靜態(tài)分配內(nèi)存的數(shù)組的長(zhǎng)度**!
(4)sizeof不能求得動(dòng)態(tài)分配的內(nèi)存的大小!
(5)sizeof不能對(duì)不完整的數(shù)組求長(zhǎng)度;
(6)當(dāng)表達(dá)式作為sizeof的操作數(shù)時(shí),**它返回表達(dá)式的計(jì)算結(jié)果的類(lèi)型大小,**但是它不對(duì)表達(dá)式求值!
(7)sizeof可以對(duì)函數(shù)調(diào)用求大小,并且求得的大小等于返回類(lèi)型的大小,但是不執(zhí)行函數(shù)體!
(8)sizeof求得的結(jié)構(gòu)體(及其對(duì)象)的大小**并不等于**各個(gè)數(shù)據(jù)成員對(duì)象的大小之和!
(9)sizeof不能用于求結(jié)構(gòu)體的位域成員的大小,但是可以求得包含位域成員的結(jié)構(gòu)體的大??!

sizeof函數(shù)總結(jié)
 
**sizeof函數(shù)功能:計(jì)算數(shù)據(jù)空間的字節(jié)數(shù)**
1.與strlen()比較
strlen計(jì)算**字符數(shù)組的字符數(shù)**,以"\0"為結(jié)束判斷,不計(jì)算為'\0'的數(shù)組元素。
sizeof計(jì)算數(shù)據(jù)(包括數(shù)組、變量、類(lèi)型、結(jié)構(gòu)體等)所占內(nèi)存空間,用字節(jié)數(shù)表示(當(dāng)然用在字符數(shù)組計(jì)算"\0"的大?。?。

**2.指針與靜態(tài)數(shù)組的sizeof操作**
指針均可看為變量類(lèi)型的一種。所有指針變量的sizeof 操作結(jié)果均為4。
實(shí)例1::char *p;
sizeof(p)=4;
sizeof(*p) = 1;   //相當(dāng)于sizeof(char);  

實(shí)例2:  
**對(duì)于靜態(tài)數(shù)組,sizeof可直接計(jì)算數(shù)組大??;**
例:int a[10];
char b[]="hello";
sizeof(a)等于4*10=40;
sizeof(b)等于6;
void  fun(char p[])
{
     sizeof(p);         //等于4,數(shù)組做型參時(shí),數(shù)組名稱(chēng)當(dāng)作指針使用!!
}

實(shí)例3(經(jīng)典考題):
double* (*a)[3][6];
cout<<sizeof(a)<<endl; // 4 a為**指針**
cout<<sizeof(*a)<<endl; // 72 *a為一個(gè)有3*6個(gè)指針元素的**數(shù)組**
cout<<sizeof(**a)<<endl; // 24 **a為**數(shù)組一維的6個(gè)指針**
cout<<sizeof(***a)<<endl; // 4 ***a為**一維的第一個(gè)指針**
cout<<sizeof(****a)<<endl; // 8 ****a為**一個(gè)double變量**
問(wèn)題解析:
a是一個(gè)很奇怪的定義,他表示一個(gè)指向double*[3][6]類(lèi)型數(shù)組的指針。既然是指針,所以sizeof(a)就是4。
既然a是執(zhí)行double*[3][6]類(lèi)型的指針,*a就表示一個(gè)double*[3][6]的多維數(shù)組類(lèi)型,因此sizeof(*a)=3*6*sizeof(double*)=72。
同樣的,**a表示一個(gè)double*[6]類(lèi)型的數(shù)組,sizeof(**a)=6*sizeof  (double*)=24。
***a就表示其中的一個(gè)元素,也就是double*了,所以sizeof(***a)=4。
****a,就是一個(gè)double了,所以sizeof(****a)=sizeof(double)=8。

3.格式的寫(xiě)法
sizeof操作符,對(duì)變量或?qū)ο罂梢圆患永ㄌ?hào),但若是類(lèi)型,須加括號(hào)。

4.使用sizeof時(shí)string的注意事項(xiàng)
string s="hello";
sizeof(s)等于string類(lèi)的大?。?2),sizeof(s.c_str())得到的是與字符串長(zhǎng)度(4)。

5.union 與struct的空間計(jì)算
總體上遵循兩個(gè)原則:
(1)**整體空間**是**占用空間最大的成員(類(lèi)型)所占字節(jié)的整數(shù)倍**
(2)數(shù)據(jù)**對(duì)齊原則**----數(shù)據(jù)在內(nèi)存中按照結(jié)構(gòu)成員**先后順序**進(jìn)行排序,**當(dāng)排到該成員變量時(shí),其前面已擺放的空間大小必須是該成員類(lèi)型大小的整倍數(shù),如果不夠則補(bǔ)齊,以此向后類(lèi)推。**

注意:數(shù)組按照單個(gè)變量一個(gè)一個(gè)的擺放,而不是看成整體。如果成員中有自定義的類(lèi)、結(jié)構(gòu)體,也要注意數(shù)組問(wèn)題。
      在計(jì)算結(jié)構(gòu)體的sizeof時(shí),需要 先求出占用空間最大的成員(類(lèi)型)所占字節(jié)來(lái)確定對(duì)齊的方式。

實(shí)例4:
因?yàn)閷?duì)齊問(wèn)題使結(jié)構(gòu)體的sizeof變得比較復(fù)雜,看下面的例子:(默認(rèn)對(duì)齊方式下)
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
同樣是兩個(gè)char類(lèi)型,一個(gè)int類(lèi)型,一個(gè)double類(lèi)型,但是因?yàn)閷?duì)齊問(wèn)題,導(dǎo)致他們的大小不同。**計(jì)算結(jié)構(gòu)體大小可以采用元素?cái)[放法**,我舉例子說(shuō)明一下:首先,CPU判斷結(jié)構(gòu)體的對(duì)界,根據(jù)上一節(jié)的結(jié)論,s1和s2的對(duì)界都取最大的元素類(lèi)型,也就是double類(lèi)型的對(duì)界8。然后開(kāi)始擺放每個(gè)元素。

對(duì)于s1,**首先把a(bǔ)放到8的對(duì)界,假定是0,此時(shí)下一個(gè)空閑的地址是1,但是下一個(gè)元素b是double類(lèi)型,要放到8的對(duì)界上,離1最接近的地址是8了,所以b被放在了8,此時(shí)下一個(gè)空閑地址變成了16,**下一個(gè)元素c的對(duì)界是4,16可以滿足,所以c放在了16,此時(shí)下一個(gè)空閑地址變成了20,下一個(gè)元素d需要對(duì)界1,也正好落在對(duì)界上,所以d放在了20,**結(jié)構(gòu)體在地址21處結(jié)束。由于s1的大小需要是8的倍數(shù),所以21-23的空間被保留,s1的大小變成了24。**

對(duì)于s2,首先把a(bǔ)放到8的對(duì)界,假定是0,此時(shí)下一個(gè)空閑地址是1,下一個(gè)元素的對(duì)界也是1,所以b擺放在1,下一個(gè)空閑地址變成了2;下一個(gè)元素c的對(duì)界是4,所以取離2最近的地址4擺放c,下一個(gè)空閑地址變成了8,下一個(gè)元素d的對(duì)界是8,所以d擺放在8,所有元素?cái)[放完畢,結(jié)構(gòu)體在15處結(jié)束,占用總空間為16,正好是8的倍數(shù)。

這里有個(gè)陷阱,**對(duì)于結(jié)構(gòu)體中的結(jié)構(gòu)體成員,不要認(rèn)為它的對(duì)齊方式就是他的大小,**看下面的例子:
實(shí)例5:
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的對(duì)齊方式是1(注意s1的大小8),s2是8(double),所以在s3和s4中才有這樣的差異。

所以,在自己定義結(jié)構(gòu)體的時(shí)候,如果空間緊張的話,最好考慮對(duì)齊因素來(lái)排列結(jié)構(gòu)體里的元素。
   相關(guān)常數(shù):
   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
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容