- 論壇徽章:
- 0
|
解析C語(yǔ)言中的sizeof
一、sizeof的概念
sizeof是C語(yǔ)言的一種單目操作符,如C語(yǔ)言的其他操作符++、--等。它并不是函數(shù)。[color="#0000ff"]sizeof操作符以字節(jié)形式給出了其操作數(shù)的存儲(chǔ)大小。操作數(shù)可以是一個(gè)表達(dá)式或括在括號(hào)內(nèi)的類型名。操作數(shù)的存儲(chǔ)大小由操作數(shù)的類型決定。
二、sizeof的使用方法
1、用于數(shù)據(jù)類型
sizeof使用形式:sizeof(type)
數(shù)據(jù)類型必須用括號(hào)括住。如sizeof(int)。
2、用于變量
sizeof使用形式:sizeof(var_name)或sizeof var_name
變量名可以不用括號(hào)括住。如sizeof (var_name),sizeof var_name等都是正確形式。帶括號(hào)的用法更普遍,大多數(shù)程序員采用這種形式。
注意:sizeof操作符不能用于函數(shù)類型,不完全類型或位字段。不完全類型指具有未知存儲(chǔ)大小的數(shù)據(jù)類型,如未知存儲(chǔ)大小的數(shù)組類型、未知內(nèi)容的結(jié)構(gòu)或聯(lián)合類型、void類型等。
如sizeof(max)若此時(shí)變量max定義為int max(),sizeof(char_v) 若此時(shí)char_v定義為char char_v [MAX]且MAX未知,sizeof(void)都不是正確形式。
三、sizeof的結(jié)果
sizeof操作符的結(jié)果類型是size_t,它在頭文件中typedef為unsigned int類型。該類型保證能容納實(shí)現(xiàn)所建立的最大對(duì)象的字節(jié)大小。
1、若操作數(shù)具有類型char、unsigned char或signed char,其結(jié)果等于1。
ANSI C正式規(guī)定字符類型為1字節(jié)。
2、int、unsigned int 、short int、unsigned short 、long int 、unsigned long 、
float、double、long double類型的sizeof 在ANSI C中沒(méi)有具體規(guī)定,大小依賴于實(shí)現(xiàn),一般可能分別為2、2、2、2、
4、4、4、8、10。
3、當(dāng)操作數(shù)是指針時(shí),sizeof依賴于編譯器。例如Microsoft C/C++7.0中,near類指針字節(jié)數(shù)為2,far、huge類指針字節(jié)數(shù)為4。一般Unix的指針字節(jié)數(shù)為4。
4、當(dāng)操作數(shù)具有數(shù)組類型時(shí),其結(jié)果是數(shù)組的總字節(jié)數(shù)。
5、聯(lián)合類型操作數(shù)的sizeof是其最大字節(jié)成員的字節(jié)數(shù)。結(jié)構(gòu)類型操作數(shù)的sizeof是這種類型對(duì)象的總字節(jié)數(shù),包括任何墊補(bǔ)在內(nèi)。
讓我們看如下結(jié)構(gòu):
struct a;
在某些機(jī)器上sizeof(a)=12,而一般sizeof(char)+ sizeof(double)=9。
這是因?yàn)榫幾g器在考慮對(duì)齊問(wèn)題時(shí),在結(jié)構(gòu)中插入空位以控制各成員對(duì)象的地址對(duì)齊。如double類型的結(jié)構(gòu)成員x要放在被4整除的地址。
6、如果操作數(shù)是函數(shù)中的數(shù)組形參或函數(shù)類型的形參,sizeof給出其指針的大小。
四、sizeof與其他操作符的關(guān)系
sizeof的優(yōu)先級(jí)為2級(jí),比/、%等3級(jí)運(yùn)算符優(yōu)先級(jí)高。它可以與其他操作符一起組成表達(dá)式。如i*sizeof(int);其中i為int類型變量。
五、sizeof的主要用途
1、sizeof操作符的一個(gè)主要用途是與存儲(chǔ)分配和I/O系統(tǒng)那樣的例程進(jìn)行通信。例如:
void *malloc(size_t size),
size_t fread(void * ptr,size_t size,size_t nmemb,FILE * stream)。
2、sizeof的另一個(gè)的主要用途是計(jì)算數(shù)組中元素的個(gè)數(shù)。例如:
void * memset(void * s,int c,sizeof(s))。
六、建議
由于操作數(shù)的字節(jié)數(shù)在實(shí)現(xiàn)時(shí)可能出現(xiàn)變化,建議在涉及到操作數(shù)字節(jié)大小時(shí)用ziseof來(lái)代替常量計(jì)算。
sizeof 用法集錦
2008-10-19 16:28
sizeof()用法匯總
sizeof()功能:計(jì)算數(shù)據(jù)空間的字節(jié)數(shù)
1.與strlen()比較
strlen()計(jì)算字符數(shù)組的字符數(shù),以"\0"為結(jié)束判斷,不計(jì)算為'\0'的數(shù)組元素。
而sizeof計(jì)算數(shù)據(jù)(包括數(shù)組、變量、類型、結(jié)構(gòu)體等)所占內(nèi)存空間,用字節(jié)數(shù)表示。
2.指針與靜態(tài)數(shù)組的sizeof操作
指針均可看為變量類型的一種。所有指針變量的sizeof 操作結(jié)果均為4。
注意:int *p; sizeof(p)=4;
但sizeof(*p)相當(dāng)于sizeof(int);
對(duì)于靜態(tài)數(shù)組,sizeof可直接計(jì)算數(shù)組大;
例:int a[10];char b[]="hello";
sizeof(a)等于4*10=40;
sizeof(b)等于6;
注意:數(shù)組做型參時(shí),數(shù)組名稱當(dāng)作指針使用!!
void fun(char p[])
{sizeof(p)等于4}
經(jīng)典問(wèn)題:
double* (*a)[3][6];
cout為指針
cout為一個(gè)有3*6個(gè)指針元素的數(shù)組
cout為數(shù)組一維的6個(gè)指針
cout為一維的第一個(gè)指針
cout為一個(gè)double變量
問(wèn)題解析:a是一個(gè)很奇怪的定義,他表示一個(gè)指向double*[3][6]類型數(shù)組的指針。既然是指針,所以sizeof(a)就是4。
既然a是執(zhí)行double*[3][6]類型的指針,*a就表示一個(gè)double*[3][6]的多維數(shù)組類型,因此sizeof(*a)=3*6*sizeof(double*)=72。同樣的,**a表示一個(gè)double*[6]類型的數(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),但若是類型,須加括號(hào)。
4.使用sizeof時(shí)string的注意事項(xiàng)
string s="hello";
sizeof(s)等于string類的大小,sizeof(s.c_str())得到的是與字符串長(zhǎng)度。
5.union 與struct的空間計(jì)算
總體上遵循兩個(gè)原則:
(1)整體空間是 占用空間最大的成員(的類型)所占字節(jié)數(shù)的整倍數(shù)
(2)數(shù)據(jù)對(duì)齊原則----內(nèi)存按結(jié)構(gòu)成員的先后順序排列,當(dāng)排到該成員變量時(shí),其前面已擺放的空間大小必須是該成員類型大小的整倍數(shù),如果不夠則補(bǔ)齊,以此向后類推。。。。。
注意:數(shù)組按照單個(gè)變量一個(gè)一個(gè)的擺放,而不是看成整體。如果成員中有自定義的類、結(jié)構(gòu)體,也要注意數(shù)組問(wèn)題。
例:[引用其他帖子的內(nèi)容]
因?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同樣是兩個(gè)char類型,一個(gè)int類型,一個(gè)double類型,但是因?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ì)界都取最大的元素類型,也就是double類型的對(duì)界8。然后開(kāi)始擺放每個(gè)元素。
對(duì)于s1,首先把a(bǔ)放到8的對(duì)界,假定是0,此時(shí)下一個(gè)空閑的地址是1,但是下一個(gè)元素d是double類型,要放到8的對(duì)界上,離1最接近的地址是8了,所以d被放在了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ì)齊方式就是他的大小,看下面的例子:
struct s1
{
char a[8];
};
struct s2
{
double d;
};
struct s3
{
s1 s;
char a;
};
struct s4
{
s2 s;
char a;
};
cout和s2大小雖然都是8,但是s1的對(duì)齊方式是1,s2是8(double),所以在s3和s4中才有這樣的差異。
所以,在自己定義結(jié)構(gòu)體的時(shí)候,如果空間緊張的話,最好考慮對(duì)齊因素來(lái)排列結(jié)構(gòu)體里的元素。
補(bǔ)充:不要讓double干擾你的位域
在結(jié)構(gòu)體和類中,可以使用位域來(lái)規(guī)定某個(gè)成員所能占用的空間,所以使用位域能在一定程度上節(jié)省結(jié)構(gòu)體占用的空間。不過(guò)考慮下面的代碼:
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 可以看到,有double存在會(huì)干涉到位域(sizeof的算法參考上一節(jié)),所以使用位域的的時(shí)候,最好把float類型和double類型放在程序的開(kāi)始或者最后。
相關(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
本文來(lái)自ChinaUnix博客,如果查看原文請(qǐng)點(diǎn):http://blog.chinaunix.net/u2/70049/showart_2136589.html |
|