【C深度剖析】sizeof操作符與數組

sizeof操作符與數組

一、  sizeof是何方神聖

說到sizeof,首先必須知道的一點:sizeof不是函數,sizeof是操作符。sizeof的作用就是,計算一個對象或類型所佔的內存字節數。


  1.1 sizeof的語法

        sizeof()

這也正是爲什麼sizeof會有那麼多人誤解其爲函數。括號裏面可以是一個數據對象,也可以是一個數據類型。對於有括號的這種語法來說,你大可以不用理會括號裏面是一個數據類型還是一個數據對象。

sizeof object:

初次見面,以爲是語法錯誤,其實這也是sizeof的一種用法,計算數據對象所佔的內存字節數。如果計算的是一個數據類型,那麼請用上面的括號形式。如此看來,那麼多程序員使用()的語法形式是有道理的,因爲放之四海皆準。


1.2 sizeof如何計算大小

如果你學習過JAVA,那麼你會發現,JAVA中根本不存在sizeof操作符。難道是因爲JAVA不夠完善嗎?其實不然。JAVA之所以沒有sizeof操作符,也正如JAVA設計者所言:JAVA不需要sizeofJAVA的運行時需要JVM的,不同的操作系統都有對應的JVM,在JVM中保證了所有類型的大小一致,不管你運行在32位還是64位的機器上,數據類型的大小都是已知的,這也正是JAVA可移植性能夠實現的最根本的原因。回到話題來,爲什麼C/C++需要sizeof?顯然,對於一個合格的C程序員,我們應該知道,我們所寫的程序運行在不同結構的機器上的時候,類型的大小有所區別。當我們需要知道一個類型的大小才能繼續寫程序的時候,我們就需要sizeof。這就是爲什麼我們需要sizeof


、  數組並沒有那麼簡單

  數組和指針是C語言中的重頭戲,那麼數組是什麼數據類型呢?按照其他書籍的介紹,數組是複合類型(與基本數據類型結合構成的類型)。數組是同一類型的數據的集合,在內存中的表現爲一串連續的內存,內存的大小爲單個數據類型的大小與數據量的乘積。在我個人看來,數組更應該稱爲數據結構。數據結構中的順序表,其實現的核心就是數組。由此可見,數組更像是一種C語言預先定義的數據結構。


  2.1 數組的語法



數據類型 數組名[數據個數]

倘若我們在定義的時候就初始化,那麼數組中第一個維度的數據大小可以不寫。


 2.2 數組名到底是什麼

數組名是一段內存空間的名字,其指向了這段內存空間。我們講到了sizeof,那麼sizeof(數組名)計算出來的,理所應當計算的就是數組名指向的這段內存空間的字節數,事實也正是如此。但是,當我們對數組名繼續深究下去,我們就會開始對sizeof(數組名)疑惑了。看下面的例子:

int arr[3] = {0,1,2};
printf(“%p”,arr);

上面的例子,打印的將會是數組首元素的地址。由此我們可以推測:arr是一個指針。我們這麼推測是有理由的,因爲指針才能存儲一個地址。但是倘若我們想現在下定論,就需要考慮sizeof(arr)。這時候你再來回答,sizeof(arr)的大小是多少。兩種答案:4或者12。答案是4的顯示,我們把arr當做一個指針,指針的內存在所佔的字節數爲412則是把數組名看做一種數據結構,這個數據結構的大小爲12字節。正確答案大家知道是12。到這裏我們的疑惑就更深了,既然編譯器認爲arr不是指針,但是arr在打印地址的時候,又保存了一個地址。這就是我們需要說的:數組名是一個類似於指針的數據結構變量名。在普通情況下,我們可以把數組名當做指針來使用。繼續看下面的一個例子:

int arr[3] = {0,1,2};
int arr2[3] = {3,4,5};
arr= arr2;

上面的代碼我們想完成的事情是將arr2數組賦值給arr數組,但是編譯的時候是錯誤的,因爲arr在表現爲指針屬性的時候,實際上是一個常量指針。我們不會對一個已經初始化了的變量再次賦值。

 2.3 數組作爲函數參數

  當數組作爲函數形參的時候,數組名則淪爲指針,既然是一個指針,我們就可以對其自增、自減和修改。在函數體內,數組名僅僅作爲一個數組的指針。我們知道了他是指針,只要我們搞清楚這個指針實際指向的數據類型,那麼對於指針的使用就顯得簡單了。



、  sizeof與數組

看下面的一段代碼:

int arr[2][2] = {
{0,1},
{2,3}
};
printf(“%d,”,sizeof(arr));
printf(“%d,”,sizeof(arr[0]));
printf(“%d\n”,sizeof(arr[0][0]));

三個printf將會打印什麼?答案:16,8,4


 3.1 sizeof(arr)


弄清楚答案的緣由我們先了解一下多維數組。

C/C++中,多維數組實際上是一位數組。多維數組在分配內存的時候,是分配一段完整的連續的內存空間。這麼說可能理解不深刻。我們先來了解一下JAVA中的多維數組,就以二維數組來看。JAVA中的二維數組在分配空間的時候,首先會分配一個大小爲2的數組,其保存的是2個一維數組的起始地址。這兩個一維數組在內存上並不一定是連續的。再看看C中的數組,就能理解其完整的連續的意思。

正是因爲如此,所以sizeof(arr)纔會打印16。因爲sizeof計算的是數組名對應的內存空間的大小,不管維度大小。


 3.2 sizeof(arr[0])


   接下來我們看一下sizeof(arr[0])。如果外面沒有sizeof操作符,arr[0]在此處如果換成指針來看待,其運算如下:(arr + 0 ),其指向的依然是數組的首行首元素的地址。但是在sizeof操作符下,arr[0]顯然不能夠當做指針來看待,這時應該理解爲二維數組的一維數組(邏輯上是如此,實際上多維數組還是一位數組)。arr[0]指向的是第一行的一位數組,我們可以理解爲arr[0]就是一個數組名,其內存空間爲arr數組的前2個元素對應的內存空間,我們sizeof,得到的結果就應該爲8


 3.2 sizeof(arr[0][0])


最後來看sizeof(arr[0][0])arr[0][0]表示訪問的是二維數組的首行一維數組的首元素,其變量就是一個int類型,所以結果爲4

由此看來,數組名與sizeof操作符搭配的時候,其表現也並不簡單,其依然還是保留了數組名作爲一種數據結構的特性。



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章