C 中sizeof用法總結

2021-07-11 19:53:14 字數 3574 閱讀 1076

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.

其返回值型別為size_t,在標頭檔案stddef.h中定義。這是乙個依賴於編譯系統的值,一般定義為:typedef unsigned int size_t;

世上編譯器林林總總,但作為乙個規範,它們都會保證char、signed char和unsigned char的sizeof值為1,畢竟char是我們程式設計能用的最小資料型別。

2. sizeof用法

(1)基本型別

char:1short:2int:4long:8double:8float:4

(不同機器不一樣)

sizeof(2);// 2的型別為int,所以等價於 sizeof( int ); 

sizeof( 2 +3.14); // 3.14的型別為double,2也會被提公升成double型別,所以等價於 sizeof( double );

(2)函式呼叫

sizeof也可以對乙個函式呼叫求值(不是函式!!!),其結果是函式返回型別的大小,函式並不會被呼叫。

(3)指標

看機器,32位為4,64位為8。

(4)陣列

陣列的sizeof值等於陣列所占用的記憶體位元組數

char a1 = "abc";   

sizeof( a1 );// 結果為4,字元末尾還存在乙個null終止符

int a2[3];       

sizeof( a2 ); // 結果為3*4=12(依賴於int)

注意:函式引數a3已不再是陣列型別,而是蛻變成指標!

(4)union

結構體在記憶體組織上是順序式的,聯合體則是重疊式,各成員共享一段記憶體,所以整個聯合體的sizeof也就是每個成員sizeof的最大值。

結構體的成員也可以是復合型別,這裡,復合型別成員是被作為整體考慮的。

union u    ;//sizeof (u) == 4

(5)struct

不用說,最煩人的部分就是struct了,因為涉及位元組對齊。

為什麼需要位元組對齊?

這樣有助於加快計算機的取數速度,否則就得多花指令週期了。為此,編譯器缺省會對結構體進行處理(實際上其它地方的資料變數也是如此),讓寬度為2的基本資料型別(short等)都位於能被2整除的位址上,讓寬度為4的基本資料型別(int等)都位於能被4整除的位址上,以此類推。這樣,兩個數中間就可能需要加入填充位元組,所以整個結構體的sizeof值就增長了。

位元組對齊的細節和編譯器實現相關,但一般而言,滿足三個準則

1)結構體變數的首位址能夠被其最寬基本型別成員的大小所整除;

2)結構體每個成員相對於結構體首位址的偏移量(offset)都是成員大小的整數倍,如有需要編譯器會在成員之間加上填充位元組(internal padding);

3)結構體的總大小為結構體最寬基本型別成員大小的整數倍,如有需要編譯器會在最末乙個成員之後加上填充位元組(trailing padding)。

需要說明的是,1)和2)描述的就是前面所說,結構體成員的位址(由首位址和偏移位址決定)為其大小的整數倍。

常見例子:

1)struct s1    ;

對於準則1),編譯器會將這個結構體的首位址位於int,也就是4的整數倍上,然後對於第乙個成員char,占用1個位元組,對於第二個成員int,根據準則2),偏移量應該為4,所以在char和int成員之間填充3個位元組(0xcc)。所以總共占用8個位元組,準則3)也實現了

2)struct s2   ;

同理,準則1)由編譯器分配記憶體位址實現,然後準則2)此處無用,自動實現了。因為準則3),所以在char後面填充3個位元組(0xcc)。

3)struct s3    ;

s1的最寬簡單成員的型別為int,s3在考慮最寬簡單型別成員時是將s1「打散」看的,所以s3的最寬簡單型別為int,通過s3定義的變數,其儲存空間首位址需要被4整除,整個sizeof(s3)的值也應該被4整除。

c1的偏移量為0,s的偏移量呢這時s是乙個整體,它作為結構體變數也滿足前面三個準則,所以其大小為8,偏移量為4(int的整數倍),c1與s之間便需要3個填充位元組,而c2與s之間就不需要了,所以c2的偏移量為12,算上c2的大小為13,13是不能被4整除的,這樣末尾還得補上3個填充位元組。最後得到sizeof(s3)的值為16。

3. sizeof和strlen區別

(1)sizeof操作符的結果型別是size_t,它在標頭檔案中typedef為unsigned int型別。該型別保證能容納實現所建立的最大物件的位元組大小。

(2)sizeof是運算子,strlen是函式。

(3)strlen(char*)函式求的是字串的實際長度,它求得方法是從開始到遇到第乙個'\0';如果你只定義沒有給它賦初值,這個結果是不定的,它會從aa首位址一直找下去,直到遇到'\0'停止。(不包含'\0');sizeof()函式返回的是變數宣告後所佔的記憶體數,不是實際長度。

(4)sizeof可以用型別做引數,strlen只能用char*做引數,且必須是以''\0''結尾的。

(5)陣列做sizeof的引數不退化,傳遞給strlen就退化為指標了。

(6)大部分編譯程式在編譯的時候就把sizeof計算過了是型別或是變數的長度這就是sizeof(x)可以用來定義陣列維數的原因。strlen的結果要在執行的時候才能計算出來,是用來計算字串的長度,不是型別佔記憶體的大小。

(7)sizeof 操作符不能返回被動態分派的陣列或外部陣列的尺寸

(8)strlen只能用char*做引數,且必須是以''\0''結尾的,而sizeof可用型別做引數,還可用函式做引數

關鍵點:

其實理解 sizeof 只需要抓住乙個要點:棧

程式儲存分布有三個區域:棧、靜態和動態(堆)。能夠從**直接操作的物件,包括任何型別的變數、指標,都是在棧上的;動態和靜態儲存區是靠棧上的所有指標間接操作的。

sizeof 操作符,計算的是物件在棧上的投影體積;記住這個就很多東西都很清楚了。

需要說明的是:

sizeof的計算發生在編譯時刻,所以可以當作常量表示式來使用(c99標準規定sizeof也可以在執行時刻進行計算)

c99標準規定,函式、不能確定型別的表示式以及位域(bit-field)成員不能被計算sizeof值

編譯器的pack指令用來調整結構體對齊方式的,不同編譯器名稱和用法略有不同

sizeof用法總結

在vc中,sizeof有著許多的用法,而且很容易引起一些錯誤。下面根據sizeof後面的 引數對sizeof的用法做個總結。a 引數為資料型別或者為一般變數。例如sizeof int sizeof long 等等。這種情 況要注意的是不同系統系統或者不同編譯器得到的結果可能是不同的。例如int型別在...

sizeof 用法總結

sizeof 功能 計算資料空間的位元組數 1.與strlen 比較 strlen 計算字元陣列的字元數,以 0 為結束判斷。而sizeof計算資料 包括陣列 變數 型別 結構體等 所佔記憶體空間,用位元組數表示 2.指標與靜態陣列的sizeof操作 指標均可看為變數型別的一種。所有指標變數的siz...

sizeof用法總結

sizeof用法總結 以下執行環境都是一般的,在32位編譯環境中 1,基本資料型別的sizeof cout 再看示例 pragma pack push 將當前pack設定壓棧儲存 pragma pack 2 必須在結構體定義之前使用 struct s1 struct s3 pragma pack p...