關於sizeof 的一些思考

2021-06-28 11:30:19 字數 4539 閱讀 2637

今天面試被問到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...