今天面試被問到sizeof,回來整理一下。
1、定義
sizeof是c/c++中的乙個操作符(operator),作用就是返回乙個物件或者型別所佔的記憶體位元組數。
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. 返回值型別為size_t,在標頭檔案stddef.h中定義。這是乙個依賴於編譯系統的值,一般定義為typedef unsigned int size_t;編譯器種類很多,但作為乙個規範,它們都會保證char、signed char和unsigned char的sizeof值為1,畢竟char是我們程式設計能用的最小資料型別。sizeof的計算發生在編譯時刻,可以被當作常量表示式使用。
2、sizeof語法:
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
實際上,sizeof計算物件的大小也是轉換成物件型別的計算,也就是說,同種型別的不同物件其sizeof值都是一致的。這裡物件可以進一步延伸至表示式,即sizeof可以對乙個表示式求值,編譯器根據表示式的最終結果型別來確定大小,一般不會對表示式進行計算。如:
sizeof( 2 ); // 2的型別為int,所以等價於 sizeof( int );
sizeof( 2 + 3.14 ); // 3.14的型別為double,2也會被提公升成double型別,所以等價於 sizeof( double );
sizeof也可以對乙個函式呼叫求值,其結果是函式返回型別的大小,函式並不會被呼叫,我們來看乙個完整的例子:
char foo()
int main()
c99標準規定,函式、不能確定型別的表示式以及位域(bit-field)成員不能被計算sizeof值,即下面這些寫法都是錯誤的:
sizeof( foo );// error
void foo2()
sizeof( foo2() );// error
struct s
;sizeof( s.f1 );// error
3. 基本資料型別的sizeof
這裡的基本資料型別指short、int、long、float、double這樣的簡單內建資料型別,由於它們都是和系統相關的,所以在不同的系統下取值可能不同,這務必引起我們的注意,盡量不要在這方面給自己程式的移植造成麻煩。一般的,在32位編譯環境中,sizeof(int)的取值為4。
4. 指標變數的sizeof
指標記錄了另乙個物件的位址。所以在32位計算機中,乙個指標變數的返回值是4,在64位系統中指標變數的sizeof結果為8。
char* pc = "abc";
int* pi;
string* ps;
char** ppc = &pc;
void (*pf)();// 函式指標
sizeof( pc ); // 結果為4
sizeof( pi ); // 結果為4
sizeof( ps ); // 結果為4
sizeof( ppc ); // 結果為4
sizeof( pf );// 結果為4
5. 陣列的sizeof
陣列的sizeof值等於陣列所占用的記憶體位元組數,如:
char a1 = "abcd";
int a2[3];
sizeof( a1 ); // 結果為5,字元末尾還存在乙個null終止符
sizeof( a2 ); // 結果為3*4=12(依賴於int)
怎麼用sizeof求陣列元素的個數呢,通常有下面兩種寫法:
int c1 = sizeof( a1 ) / sizeof( char ); // 總長度/單個元素的長度
int c2 = sizeof( a1 ) / sizeof( a1[0] ); // 總長度/第乙個元素的長度
下面的c3,c4值應該是多少呢
void foo3(char a3[5])
void foo4(char a4)
這裡函式形參a3已不再是陣列型別,而是蛻變成指標,相當於char* a3。
6. struct的sizeof
這是初學者問得最多的乙個問題,所以這裡有必要多費點筆墨。讓我們先看乙個結構體:
struct s1
;sizeof(s1)等於多少?char佔1個位元組,int佔4個位元組,那麼加起來就應該是5。但是在機器上得到的結果為8。為什麼呢?是因為位元組對齊啊!位元組對齊有助於加快計算機的取數速度,否則就得多花指令週期了。為此,編譯器缺省會對結構體進行處理(實際上其它地方的資料變數也是如此),讓寬度為2的基本資料型別(short等)都位於能被2整除的位址上,讓寬度為4的基本資料型別(int等)都位於能被4整除的位址上,以此類推。這樣,兩個數中間就可能需要加入填充位元組,所以整個結構體的sizeof值就增長了。
struct test1 ;
sizeof(test1)=12
struct test1 ;
sizeof(test1)=12
struct test1 ;
sizeof(test1)=12
struct test1 ;
sizeof(test1)=12
struct test1 ;
sizeof(test1)=16
struct test1 ;
sizeof(test1)=16
這下就明白了吧?
7. class的sizeof
來看看例子:
class parent
~parent() {}
void set() {}
int get() {}
};class child:parent
~child() {}
};int main(int argc, char* argv)
class的sizeof只計算了class的變數,函式沒有涉及。但是虛函式呢?
例1:
class parent
~parent() {}
void set() {}
int get() {}
virtual void func01() {}
};class child:parent
~child() {}
};int main(int argc, char* argv)
例2:
class parent
~parent() {}
void set() {}
int get() {}
virtual void func01() {}
};class child:parent
~child() {}
virtual void func11() {}
};int main(int argc, char* argv)
例3:
class parent
~parent() {}
void set() {}
int get() {}
virtual void func01() {}
virtual void func02() {}
virtual void func03() {}
virtual void func04() {}
};class child:parent
~child() {}
virtual void func11() {}
};int main(int argc, char* argv)
例4:
class parent
virtual ~parent() {}
void set() {}
int get() {}
virtual void func01() {}
};class child:parent
~child() {}
virtual void func11() {}
};int main(int argc, char* argv)
說明sizeof只計算class裡面的變數空間,如果有虛函式的話,還有虛函式表的位址4byte,當然不管虛函式是普通的虛函式還是虛析構函式,都是放在同乙個虛函式表裡面。子類和父類使用的是同乙個虛函式表。
參考文章:
c++ 虛函式表解析
關於SpringIOC的一些思考
ioc是 依賴倒置原則 的乙個特例,說其是特例,就是說其具有 依賴倒置原則 的性質。依賴倒置原則強調的兩點是 上層模組和下次模組都依賴於抽象,二者之間通過這種抽象的東西聯絡在一起 具體可以依賴於抽象,而抽象不能依賴於具體。我認為spring提倡的 基於介面程式設計 就是為了遵循 依賴倒置原則 其中所...
關於創意的一些思考
2016.12.2 22.20 bgm 古風 這週三的下午 27號 難得去聽了乙個講座 關於以創意為核心的動漫產業鏈價值的最大化 其實還是 由於這個話題吸引了我,演講的是上海美影的老廠長,由於時間的關係,給我們講述了在過去幾年美影廠針對傳統 動畫人物的產業鏈的發展以及注重要中國特色動漫。其實,在這幾...
關於遞迴的一些思考
遞迴函式一般有兩種模式,請看下面。include define cutoff 3 void swap int a,int b void insertionsort int array,int len else array j 1 temp int median3 int a,int left,int...