回覆列表
-
1 # IT劉小虎
-
2 # TonyDeng
sizeof()只能算出陣列定義時規定的容量,但不能用於計算陣列長度。
sizeof()是編譯期處理的常量。當代碼寫出int x;的時候,若有sizeof(x)則編譯時就直接按編譯引數指定資料長度替換為常數,比如在32位系統中,這個值是4。當代碼寫出int y[10];的時候,sizeof(y)將是40,即整個陣列容器的容量。這些都是常數,執行時是不會變的。
有些教材或學長,會跟學生說用sizeof(y)/sizeof(int)來求出值10說是陣列的長度,但實際上那是陷阱,不要這樣做。對於陣列來說,定義了能夠容納10個元素,不等於使用者就真的用了10個,他實際上可能只用了8個或是3個,甚至可能是動態使用的,陣列的長度是實際使用的元素個數,不是容器容量。陣列的長度必須動態計算。
舉個例子,C字串的長度,就不能這樣求。我們通常定義比如100個字元(不管是什麼編碼的字元)的陣列,但實際上真正用到字串的長度,是要找到第一個"\0"字元為止的字元數,這個順序查詢迴圈是省不了的(C字串的效率比其他語言低,主要也是這個原因,像BASIC這類是不用迴圈即能獲取該資料),要用型如strlen()的函式。
在C語言程式開發中,sizeof() 是一個常用,也是一個非常有用的關鍵字,程式設計師常常使用它來獲取變數佔用記憶體的位元組數。
小技巧:避免“硬解碼”造成的程式碼維護困難例如下面這樣的例子,請看相關C語言程式碼如下:
size 就等於 x 在記憶體中佔用的位元組數。在固定的機器平臺,變數 x 是 float 型別,佔用的記憶體位元組數是固定的,例如 float 型別在 pc 上常佔用 4 位元組記憶體空間。
之所以不直接使用 4,而是使用 sizeof(x) 是為了方便以後的維護。可以想象,若以後發現 x 需要使用更長的資料型別 double 才能滿足需求,只需將 float x; 修改為 double x; 就可以了,size 會自己適應修改。
其實不僅C語言,在其他語言的程式開發中,都有這樣一個原則:儘可能的避免硬解碼出現,儘可能的避免重複功能出現,這樣才有利於後期的維護——萬一需要修改程式碼,只需要修改一處。
sizeof() 獲取陣列長度的“陷阱”很多時候,利用 sizeof() 還可以獲取陣列的長度,例如下面這兩行C語言程式碼:
len 此時等於 128,也即陣列 str 的長度。但是如果陣列不是 char 型的,而是其他型別的,len 還等於陣列長度嗎?編寫如下C語言程式:
編譯並執行這段C語言程式碼,得到如下結果:
顯然,len 並不等於 arr 的長度 10,而是等於 40。很多C語言初學者看到這裡會感到迷惑,怎麼回事?sizeof(陣列名)不是等於陣列長度的嗎?
sizeof() 關鍵字從來就不是計算長度的關鍵字,而是獲取變數佔記憶體空間位元組數的關鍵字,這一點要謹記。str 是一個長度為 128 的 char 型陣列,它佔用記憶體位元組數恰好等於 128,是因為 str 的每一個元素都是 char 型的,而 char 型佔用一個位元組的記憶體空間,因此此時 str 佔用記憶體位元組數和它的長度恰好是相等的。
再來看陣列 arr,它的長度等於 10,但是它的每個元素都是 int 型的,而在我的機器上 int 型變數佔用 4 位元組記憶體空間,所以 arr 一共佔用 40 位元組記憶體空間,因此 sizeof(arr) 等於 40,而不是 10。
獲取陣列長度的小技巧現在知道 sizeof() 有時無法直接獲取陣列長度的原因了,我們完全可以如下定義一個方法,用於計算陣列長度,相關C語言程式碼如下,請看:
sizeof(陣列名)計算的是整個陣列佔用的記憶體位元組數,而 sizeof(* x) 等價於 sizeof(x[0]),也即陣列第一個元素佔用的記憶體位元組數。因為陣列中各個元素的型別是相同的,所以 sizeof(* x) 也可以認為是每一個數組元素佔用的記憶體位元組數。上述宏定義就相當於:
陣列長度 = 陣列所有元素佔用記憶體位元組數 / 每個元素佔用記憶體位元組數這麼看來, arr_len 就不難理解了。編寫如下C語言程式測試一下 arr_len:
編譯並執行上面這段C語言程式,得到如下輸出:
顯然,arr_len 計算其他型別陣列的長度也不在話下。