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