C sizeof 使用規則及陷阱分析

2021-05-21 20:09:36 字數 2932 閱讀 2467

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<

在編譯階段已經被翻譯為:

cout<<4<

這裡有個陷阱,看下面的程式:

int a = 0;

cout<

輸出為什麼是4,0而不是期望中的4,3???就在於sizeof在編譯階段處理的特性。由於sizeof不能被編譯成機器碼,所以sizeof作用範圍內,也就是()裡面的內容也不能被編譯,而是被替換成型別。=操作符返回左運算元的型別,所以a=3相當於int,而**也被替換為:

int a = 0;

cout<<4<

所以,sizeof是不可能支援鏈式表示式的,這也是和一元操作符不一樣的地方。

結論:不要把sizeof當成函式,也不要看作一元操作符,把他當成乙個特殊的編譯預處理。

2、sizeof的用法

sizeof有兩種用法:

(1)sizeof(object)

也就是對物件使用sizeof,也可以寫成sizeof object 的形式。

(2)sizeof(typename)

也就是對型別使用sizeof,注意這種情況下寫成sizeof typename是非法的。下面舉幾個例子說明一下:

int i = 2;

cout<

可以看出,加()是永遠正確的選擇。

結論:不論sizeof要對誰取值,最好都加上()。

3、資料型別的sizeof

(1)c++固有資料型別

32位c++中的基本資料型別,也就char,short int(short),int,long int(long),float,double, long double

大小分別是:1,2,4,4,4,8, 10。

考慮下面的**:

cout<

unsigned影響的只是最高位bit的意義,資料長度不會被改變的。

結論:unsigned不能影響sizeof的取值。

(2)自定義資料型別

typedef可以用來定義c++自定義型別。考慮下面的問題:

typedef short word;

typedef long dword;

cout<<(sizeof(short) == sizeof(word))<

結論:自定義型別的sizeof取值等同於它的型別原形。

(3)函式型別

考慮下面的問題:

int f1();

double f2()

void f3(){}

cout<

結論:對函式使用sizeof,在編譯階段會被函式返回值的型別取代,

4、指標問題

考慮下面問題:

cout<

可以看到,不管是什麼型別的指標,大小都是4的,因為指標就是32位的實體地址。

結論:只要是指標,大小就是4。(64位機上要變成8也不一定)。

順便唧唧歪歪幾句,c++中的指標表示實際記憶體的位址。和c不一樣的是,c++中取消了模式之分,也就是不再有small,middle,big,取而代之的是統一的flat。flat模式採用32位實位址定址,而不再是c中的 segment:offset模式。舉個例子,假如有乙個指向位址 f000:8888的指標,如果是c型別則是8888(16位, 只儲存位移,省略段),far型別的c指標是f0008888(32位,高位保留段位址,地位保留位移),c++型別的指標是f8888(32位,相當於段位址*16 + 位移,但定址範圍要更大)。

5、陣列問題

考慮下面問題:

char a = "abcdef";

int b[20] = ;

char c[2][3] = ;

cout<

陣列a的大小在定義時未指定,編譯時給它分配的空間是按照初始化的值確定的,也就是7。c是多維陣列,占用的空間大小是各維數的乘積,也就是6。可以看出,陣列的大小就是他在編譯時被分配的空間,也就是各維數的乘積*陣列元素的大小。

結論:陣列的大小是各維數的乘積*陣列元素的大小。

這裡有乙個陷阱:

int *d = new int[10];

cout<

d是我們常說的動態陣列,但是他實質上還是乙個指標,所以sizeof(d)的值是4。

再考慮下面的問題:

double* (*a)[3][6];

cout<

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。

C sizeof 使用規則及陷阱分析

1 什麼是sizeof 首先看一下sizeof在msdn上的定義 the sizeof keyword gives the amount of storage,in bytes,associated with a variable or a type including aggregate type...

C sizeof 使用規則及陷阱分析

1 什麼是sizeof 首先看一下sizeof在msdn上的定義 the sizeof keyword gives the amount of storage,in bytes,associated with a variable or a type including aggregate type...

wireshark過濾規則及使用方法

例子 ip.src eq 192.168.1.107 or ip.dst eq 192.168.1.107或者 ip.addr eq 192.168.1.107 都能顯示 ip和目標iptcp.port eq 80 不管埠是 的還是目標的都顯示 tcp.port 80 tcp.port eq 272...