sizeof小览
一、文章來由—一道面試題遷出的探究
我發(fā)現(xiàn)我已經(jīng)形成一種習(xí)慣寫來由了,以后看博客的時候能夠讓我回顧起為什么出現(xiàn)這個問題,我用什么方法解決的,既然形成習(xí)慣就讓這個習(xí)慣保持下去吧。今天實驗室?guī)熃阍诳磿?#xff0c;一處不解。是關(guān)于sizeof的,大家討論此問題后,我一向信服做了才知道答案,于是有了這篇文章。
可是僅僅能叫小覽,由于不可能總結(jié)完sizeof的使用方法,歡迎補(bǔ)充和討論。
二、從這道題目說起
我直接將問題的關(guān)鍵部分提出來:
string strArr1[] = { "Trend", "Micro", "Soft" }; cout << "sizeof(strArr1) == " << sizeof(strArr1) << endl;請問輸出多少。書上的答案這樣寫道:
而字符串strArr1是由3段構(gòu)成的,所 以sizeof(strArr1)大小是12。
首先要明白sizeof不是函數(shù),也不是一元運(yùn)算符,它是個相似宏定義的特殊關(guān)鍵字,特別是sizeof(string)=4。
這個不去試是不知道的。由于編譯器那么多。編譯器做什么事情不去試怎么可能知道
果然,在vs2013 release Win32模式(x64模式還要更大)下結(jié)果是
sizeof(string) == 24
sizeof(strArr1) == 72
debug模式
sizeof(string) == 28
sizeof(strArr1) == 84
也是3倍關(guān)系,由于這是一個string數(shù)組。里面有三個string對象
那么為什么string有不同的結(jié)果?
查閱了相關(guān)資料得出結(jié)論:我們知道char*肯定是4字節(jié),string里面可能不止包括一個char*那么簡單,還包括有長度信息等其它信息。string的實如今各庫中可能有所不同,可是在同一庫中同樣一點(diǎn)是,不管你的string里放多長的字符串,它的sizeof()都是固定的。字符串所占的空間是從堆中動態(tài)分配的,與sizeof()無關(guān)。
sizeof(string)=4可能是最典型的實現(xiàn)之中的一個,只是也有sizeof()為12、32字節(jié)的庫實現(xiàn)。 可是VC6.0測試后sizeof(string)=16.還是跟編譯器有關(guān)為了全然測試一些東西。我測試越寫越多,然后我來了威力加強(qiáng)版。見代碼:
#include<iostream>using namespace std;int main() {char p[] = { 'a', 'b', 'c', 'a', 'b', 'c' };char *p1 = "abcabc";char p2[] = "abcabc";char p3[][2] = { { 'a', 'b' }, { 'c', 'a' }, { 'b', 'c' } };printf("p == %s\n", p);cout << p << endl;cout << "sizeof(p) == " << sizeof(p) << endl;cout << "sizeof(p1) == " << sizeof(p1) << endl;cout << "sizeof(p2) == " << sizeof(p2) << endl;cout << "sizeof(p3) == " << sizeof(p3) << endl;cout<<"sizeof(string) == " << sizeof(string) << endl;string strArr1[] = { "Trend", "Micro", "Soft" };cout << "sizeof(strArr1) == " << sizeof(strArr1) << endl;int a = 0;cout <<"sizeof(a = 3) == " << sizeof(a = 3) << endl;cout << "a == " << a << endl;cout << "sizeof(999999) == " << sizeof(999999) << endl;cout << "sizeof(9999999999999999999) == " << sizeof(9999999999999999999) << endl;cout << "sizeof(9 / 5) == " << sizeof(9 / 5) << endl;cout << "sizeof((double)9 / 5) == " << sizeof((double)9 / 5) << endl;return 0; }執(zhí)行結(jié)果如圖所看到的:
我來一一解釋我的這些測試在做什么:
(1)首先p的這種初始化方式。在末尾不會加’\0’。所以 sizeof(p) == 6;并且一個有趣的問題是printf和cout直接輸出p是不同的,printf是要碰到’\0’結(jié)束,我也看了printf和cout的匯編代碼,可是沒有細(xì)究,之后又空具體研究一下
(2)p1和p2的sizeof不同。由于一個是指針,一個是字符數(shù)組。指針在Win32編譯環(huán)境下的sizeof都是4。由于是4字節(jié)的地址。32bits可尋址空間
(3)p3是還有一個有趣的問題,p3不能寫成p3[3][]來初始化,由于這樣初始化要保證二維數(shù)組每一行的個數(shù)同樣。也就是不能出現(xiàn)“參差不齊”的情況,那種情況要動態(tài)分配
(4)這是一個陷阱
輸出為什么是4。0 而不是期望中的4。3???就在于sizeof在編譯階段處理的特性。由于sizeof不能被編譯成機(jī)器碼。所以sizeof作用范圍內(nèi),也就是()里面的內(nèi)容不能被編譯,而是被替換成類型。=操作符返回左操作數(shù)的類型。所以a=3相當(dāng)于int,而代碼也被替換為:
cout<<4<<endl; cout<<a<<endl;所以,sizeof是不可能支持鏈?zhǔn)奖磉_(dá)式的。這也是和一元操作符不一樣的地方。
不要把sizeof當(dāng)成函數(shù),也不要看作一元操作符,把他當(dāng)成一個特殊的編譯預(yù)處理。
(5)這種原因是999999是一個編譯器int型能夠搞定的數(shù)。所以按int來處理,太大的數(shù)不能用int搞定,可是8個字節(jié)一定能夠搞定的
sizeof(999999) == 4
sizeof(9999999999999999999) == 8
(6)最后是看了(9 / 5)編譯器是作為int看待的。強(qiáng)制轉(zhuǎn)換后才是double
三、sizeof 能總結(jié)多少是多少
sizeof博大精深。即使看了非常多資料,一口氣總結(jié)完也是不可能了,總結(jié)經(jīng)常使用的就好。
1、什么是sizeof
首先看一下sizeof在msdn上的定義:
The sizeof keyword gives the amount of storage, in bytes, associated with a variable or a type (including aggregate types). This keyword returns a value of type size_t.
看到return這個字眼,是不是想到了函數(shù)?錯了,sizeof不是一個函數(shù)。你見過給一個函數(shù)傳參數(shù),而不加括號的嗎?sizeof能夠,所以sizeof不是函數(shù)。網(wǎng)上有人說sizeof是一元操作符。可是我并不這么覺得,由于sizeof更像一個特殊的宏,它是在編譯階段求值的。
舉個樣例:
cout<<sizeof(int)<<endl; // 32位機(jī)上int長度為4 cout<<sizeof(1==2)<<endl; // == 操作符返回bool類型。相當(dāng)于 cout<<sizeof(bool)<<endl; 在編譯階段已經(jīng)被翻譯為: cout<<4<<endl; cout<<1<<endl;2、語法
sizeof有三種語法形式。例如以下:
1) sizeof( object ); // sizeof( 對象 );
2) sizeof( type_name ); // sizeof( 類型 );
3) sizeof object; // sizeof 對象;
所以,
int i;
sizeof( i ); // ok
sizeof i; // ok
sizeof( int ); // ok
sizeof int; // error
既然寫法1能夠全然代替寫法3,為求形式統(tǒng)一以及降低我們大腦的負(fù)擔(dān),第3種寫法。忘掉它吧!
實際上。sizeof計算對象的大小也是轉(zhuǎn)換成對對象類型的計算。也就是說,同種類型的不同對象其sizeof值都是一致的。這里,對象能夠進(jìn)一步延伸至表達(dá)式,即sizeof能夠?qū)σ粋€表達(dá)式求值。編譯器依據(jù)表達(dá)式的終于結(jié)果類型來確定大小,一般不會對表達(dá)式進(jìn)行計算。
如:
sizeof( 2 ); // 2的類型為int。所以等價于 sizeof( int );
sizeof( 2 + 3.14 ); // 3.14的類型為double,2也會被提升成double類型。所以等價于 sizeof( double );
3、函數(shù)的sizeof
函數(shù)類型
考慮以下的問題: int f1(){return 0;}; double f2(){return 0.0;} void f3(){}cout<<sizeof(f1())<<endl; // f1()返回值為int,因此被覺得是int cout<<sizeof(f2())<<endl; // f2()返回值為double,因此被覺得是double cout<<sizeof(f3())<<endl; // 錯誤。無法對void類型使用sizeof cout<<sizeof(f1)<<endl; // 錯誤!無法對函數(shù)指針使用sizeof cout<<sizeof*f2<<endl; // *f2,和f2()等價,由于能夠看作object,所以括號不是必要的。被覺得是double結(jié)論:對函數(shù)使用sizeof,在編譯階段會被函數(shù)返回值的類型代替
4、數(shù)組的sizeof
char a[] = "abcdef"; int b[20] = {3, 4}; char c[2][3] = {"aa", "bb"};cout<<sizeof(a)<<endl; // 7 cout<<sizeof(b)<<endl; // 20*4=80 cout<<sizeof(c)<<endl; // 6數(shù)組a的大小在定義時未指定。編譯時給它分配的空間是依照初始化的值確定的。也就是7。
c是多維數(shù)組,占用的空間大小是各維數(shù)的乘積,也就是6。
能夠看出。數(shù)組的大小就是他在編譯時被分配的空間。也就是各維數(shù)的乘積*數(shù)組元素的大小。
結(jié)論:數(shù)組的大小是各維數(shù)的乘積*數(shù)組元素的大小。
這里有一個陷阱:
int *d = new int[10];cout<<sizeof(d)<<endl; // 4d是我們常說的動態(tài)數(shù)組。可是他實質(zhì)上還是一個指針,所以sizeof(d)的值是4。
再考慮以下的問題:
a是一個非常奇怪的定義,他表示一個指向 double*[3][6]類型數(shù)組的指針。
既然是指針,所以sizeof(a)就是4。
既然a是指向double*[3][6]類型的指針,*a就表示一個double*[3][6]的多維數(shù)組類型,因此sizeof(*a)=3*6*sizeof(double*)=72。同樣的,**a表示一個double*[6]類型的數(shù)組,所以sizeof(**a)=6*sizeof(double*)=24。***a就表示當(dāng)中的一個元素,也就是double*了,所以sizeof(***a)=4。至于****a,就是一個double了,所以sizeof(****a)=sizeof(double)=8。
差點(diǎn)兒相同也要結(jié)束了,假設(shè)更進(jìn)一步了解,須要查閱很多其它的資料~~~
—END—
參考文獻(xiàn)
[1] http://blog.csdn.net/freefalcon/article/details/54839
[2] http://www.cnblogs.com/wanghetao/archive/2012/04/04/2431760.html
轉(zhuǎn)載于:https://www.cnblogs.com/mthoutai/p/7131998.html
總結(jié)
- 上一篇: java 类调用情况_java 如何调用
- 下一篇: 调色板原理