詳解C++ sizeof(上)
sizeof是C/C++中的一個(gè)操作符(operator),其作用是返回一個(gè)對(duì)象或者類型所占的內(nèi)存字節(jié)數(shù),使用頻繁,有必須對(duì)其有個(gè)全面的了解。
1.sizeof的基本語(yǔ)法
sizeof有三種語(yǔ)法形式。
(1)sizeof(object); //sizeof(對(duì)象);
(2)sizeof(type_name); //sizeof(類型);
(3)sizeof object; //sizeof對(duì)象;
第三種語(yǔ)法結(jié)構(gòu)雖然簡(jiǎn)約,但并不常見,為簡(jiǎn)單統(tǒng)一,建議使用第一和第二種寫法。
int i; sizeof( i ); // ok sizeof i; // ok sizeof( int ); // ok sizeof int; // error
2.sizeof計(jì)算基本類型與表示式
sizeof計(jì)算對(duì)象的大小實(shí)際上是轉(zhuǎn)換成對(duì)象類型進(jìn)行計(jì)算,也就是說,同種類型的不同對(duì)象其sizeof值都是一致的。這里,對(duì)象可以進(jìn)一步延伸至表達(dá)式,即sizeof可以對(duì)一個(gè)表達(dá)式求值,編譯器根據(jù)表達(dá)式的最終結(jié)果類型來確定大小,sizeof是編譯時(shí)進(jìn)行運(yùn)算,與運(yùn)行時(shí)無(wú)關(guān),不會(huì)對(duì)表達(dá)式進(jìn)行計(jì)算??疾烊缦麓a:
#include <iostream> using namespace std; int main(int argc,char* argv[]) { cout<<"sizeof(char)="<<sizeof(char)<<endl; cout<<"sizeof(short)="<<sizeof(short int)<<endl; cout<<"sizeof(int)="<<sizeof(int)<<endl; cout<<"sizeof(long)="<<sizeof(long int)<<endl; cout<<"sizeof(long long)="<<sizeof(long int int)<<endl; cout<<"sizeof(float)="<<sizeof(float)<<endl; cout<<"sizeof(double)="<<sizeof(double)<<endl; int i=8; cout<<"i="<<i<<endl; cout<<"sizeof(i)="<<sizeof(i)<<endl; cout<<"sizeof(i)="<<sizeof(i=5)<<endl; cout<<"i="<<i<<endl; }
在64bits的Windows下運(yùn)行結(jié)果如下:
sizeof(char)=1
sizeof(short)=2
sizeof(int)=4
sizeof(long)=4
sizeof(long long)=4
sizeof(float)=4
sizeof(double)=8
i=8
sizeof(i)=4
sizeof(i)=4
i=8
觀察以上程序需要注意兩點(diǎn)。
(1)i的值并未發(fā)生改變,表明sizeof括號(hào)內(nèi)的表達(dá)式并沒有執(zhí)行,sizeof在編譯時(shí)求其表達(dá)式的運(yùn)算結(jié)果的類型,sizeof運(yùn)算與運(yùn)行時(shí)無(wú)關(guān)。sizeof(i)等價(jià)于sizeof(int),sizeof(i=5)等價(jià)于sizeof(int),也就是說在可執(zhí)行代碼中,并不包含i=5這個(gè)表達(dá)式,它早在編譯階段就被處理了。
(2)long int是否占8字節(jié),與編譯器的實(shí)現(xiàn)有關(guān),Visual C++在VS2012中使用的編譯器是cl.exe,在64bits的Windows下仍然將long編譯為4字節(jié),要想使用8字節(jié)長(zhǎng)整型,保險(xiǎn)起見,使用long long型。
3.sizeof計(jì)算指針變量
指針是C/C++的靈魂,它記錄了一個(gè)對(duì)象的地址。指針變量的位寬等于機(jī)器字長(zhǎng),機(jī)器字長(zhǎng)由CPU寄存器位數(shù)決定。在32位系統(tǒng)中,一個(gè)指針變量的返回值為4字節(jié),64位系統(tǒng)中指針變量的sizeof結(jié)果為8字節(jié)。
char* pc = "abc"; int* pi=new int[10]; string* ps; char** ppc = &pc; void (*pf)(); // 函數(shù)指針 char testfunc() { return ‘k'; } sizeof( pc ); // 結(jié)果為4 sizeof( pi ); // 結(jié)果為4 sizeof( ps ); // 結(jié)果為4 sizeof( ppc ); // 結(jié)果為4 sizeof( pf ); // 結(jié)果為4 sizeof( &testfunc ); // 結(jié)果為4 sizeof( testfunc ()); // 結(jié)果為1 sizeof(*( testfunc) ()); // 結(jié)果為1
考察以上代碼,得出如下結(jié)論:
(1)指針變量的sizeof值與指針?biāo)傅膶?duì)象類型沒有任何關(guān)系,與指針申請(qǐng)多少空間沒有關(guān)系,所有的指針變量所占內(nèi)存大小均相等。那為什么在本機(jī)64bits系統(tǒng)下,指針變量大小仍然是4個(gè)字節(jié),因?yàn)槭褂?2位編譯器編譯得到程序是32位,故指針大小是4字節(jié),可自行修改編譯器版本,不再贅述。
(2)&testfunc代表一個(gè)函數(shù)指針,指針大小是4,所以sizeof(&testfunc)==4。testfunc()代表一次函數(shù)調(diào)用,返回值類型是char,所以sizeof(testfunc())==sizeof(char)==1。testfunc名本身就是一個(gè)函數(shù)指針,所以(*testfunc)()
也是一次函數(shù)調(diào)用,sizeof((*testfunc)())==sizeof(char)==1
。
4.sizeof計(jì)算數(shù)組
當(dāng)sizeof作用于數(shù)組時(shí),求取的是數(shù)組所有元素所占用的大小。參考如下代碼:
int A[3][5]; char c[]="123456"; double*(*d)[3][6]; cout<<sizeof(A)<<endl; //輸出60 cout<<sizeof(A[4])<<endl; //輸出20 cout<<sizeof(A[0][0])<<endl;//輸出4 cout<<sizeof(c)<<endl; //輸出7 cout<<sizeof(d)<<endl; //輸出4 cout<<sizeof(*d)<<endl; //輸出72 cout<<sizeof(**d)<<endl; //輸出24 cout<<sizeof(***d)<<endl; //輸出4 cout<<sizeof(****d)<<endl; //輸出8
考察以上代碼,得出如下結(jié)論:
(1)A的數(shù)據(jù)類型是int[3][5]
,A[4]
的數(shù)據(jù)類型是int[5]
,A[0][0]
數(shù)據(jù)類型是int。所以
sizeof(A)==sizeof(int[3][5])==3*5*sizeof(int)==60 sizeof(A[4])==sizeof(int[5])=5*sizeof(int)==20 sizeof(A[0][0])==sizeof(int)==4
盡管A[4]
的下標(biāo)越界,但不會(huì)造成運(yùn)行時(shí)錯(cuò)誤,因?yàn)閟izeof運(yùn)算只關(guān)心數(shù)據(jù)類型,在編譯階段就已經(jīng)完成。
(2)由于字符串以空字符'\0'結(jié)尾,所以c的數(shù)據(jù)類型是char[7],所以sizeof(c)=sizeof(char[7])==7。
(3)d是一個(gè)指針,不管它指向的對(duì)象是什么數(shù)據(jù)類型,自身大小永遠(yuǎn)是4,所以sizeof(d)==4。sizeof(*d)的數(shù)據(jù)類型是double*[3][6]
,所以
sizeof(*d)==sizeof(double*[3][6])==3*6*sizeof(double*)==18*4==72
同理,可以推算出
sizeof(**d)==sizeof(double*[6])==6*sizeof(double*)==24 sizeof(***d)==sizeof(double*)==4 sizeof(****d)=sizeof(double)==8
當(dāng)數(shù)組作為函數(shù)形參時(shí),下面的i和j的值應(yīng)該是多少呢?
void foo1(char a1[3]) { int i = sizeof( a1 ); // i == ? } void foo2(char a2[]) { int j = sizeof( a2); // j == ? }
也許當(dāng)你試圖回答j的值時(shí)已經(jīng)意識(shí)到i答錯(cuò)了,是的,i!=3。這里函數(shù)參數(shù)a1已不再是數(shù)組類型,而是蛻變成指針,相當(dāng)于char* a1,為什么?仔細(xì)想想就不難明白,我們調(diào)用函數(shù)foo1時(shí),程序會(huì)在棧上分配一個(gè)大小為3的數(shù)組嗎?不會(huì)!數(shù)組是“傳址”的,調(diào)用者只需將實(shí)參的地址傳遞過去,所以a1自然為指針類型(char*),i的值也就為4,同樣j也是4。
以上就是詳解C++ sizeof(上)的詳細(xì)內(nèi)容,更多關(guān)于C++ sizeof的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
C語(yǔ)言函數(shù)棧幀的創(chuàng)建與銷毀原理圖解
我們知道c語(yǔ)言中函數(shù)都是被調(diào)用的,main函數(shù)里面能調(diào)用其他函數(shù),其實(shí)main函數(shù)也是被別的函數(shù)調(diào)用的,下面通過本文給大家分享c語(yǔ)言函數(shù)棧幀的創(chuàng)建和銷毀過程,一起看看吧2022-05-05解決Devc++運(yùn)行窗口中文亂碼的實(shí)現(xiàn)步驟
本文主要介紹了如何解決Devc++運(yùn)行窗口中文亂碼,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-06-06C++實(shí)現(xiàn)藍(lán)橋杯競(jìng)賽題目---搭積木
這篇文章主要介紹了C++實(shí)現(xiàn)藍(lán)橋杯競(jìng)賽題目---搭積木,本篇文章通過題目分析列舉公式進(jìn)行分析算法,包含詳細(xì)的圖文,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-07-07通過stringstream實(shí)現(xiàn)常用的類型轉(zhuǎn)換實(shí)例代碼
在本篇文章里小編給大家分享了關(guān)于通過stringstream實(shí)現(xiàn)常用的類型轉(zhuǎn)換實(shí)例代碼內(nèi)容,需要的朋友們可以參考下。2020-04-04OpenCV實(shí)現(xiàn)鼠標(biāo)在圖像上框選單目標(biāo)和多目標(biāo)
這篇文章主要為大家詳細(xì)介紹了OpenCV實(shí)現(xiàn)鼠標(biāo)在圖像上框選單目標(biāo)和多目標(biāo),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-08-08C++實(shí)現(xiàn)水仙花數(shù)判斷實(shí)例
大家好,本篇文章主要講的是C++實(shí)現(xiàn)水仙花數(shù)判斷實(shí)例,感興趣的同學(xué)趕快來看一看吧,對(duì)你有幫助的話記得收藏一下,方便下次瀏覽2022-01-01