什麼是陣列名

才智咖 人氣:1.57W

實際上陣列名永遠都不會是指標! 指標是C語言具有低階語言特徵的最直接的證據。在組合語言裡面,指標的概念隨處可見。比如SP,SP暫存器又叫堆疊指標,它的值是地址,由於SP儲存的是地址,並且SP的值是不斷變化的,因此可以看作一個變數,而且是一個地址變數。地址也是C語言指標的值,C語言的指標跟SP這樣的暫存器雖然不完全一樣,但原理卻是相通的。C語言的指標也是一種地址變數,C89明確規定,指標是一個儲存物件地址的變數。這裡要注意的是,指標跟地址概念的不同,指標是一種地址變數,通常也叫指標變數,統稱指標。而地址則是地址變數的值。

什麼是陣列名

看到這裡,也許你會覺得,這麼簡單的東西還用你來說嗎?的確,對於p與&p來說,99%的人都能在0.1秒內脫口而出誰是指標,誰是地址,但是,又有多少人在使用指標的過程中能夠始終如一毫不動搖地遵循這兩個概念呢?不少人使用指標的時候就會自覺或不自覺地把指標和地址兩個概念混淆得一塌糊塗了,陣列名的濫用就是一個活生生的例子。這一點甚至連一些經典著作也沒能避免。

不過也不能全怪你自己,筆者認為某些國內教材應該承擔最大的責任。這些教材一開始就沒有給讀者好好地分清指標與地址的區別,相反還在講述的過程中有意無意地混用這兩個概念。更有甚者,甚至在書中明言指標就是地址!說這話的傢伙最應該在C語言這個地圖上抹掉,呵呵。兩個月前我在購書中心隨手翻開了某個作者主編的一本被冠以國家“十五”規劃重點研究專案的書,書裡就是這麼寫的。當時筆者就感慨:不知道又要有多少人的思想被這傢伙“性暴力”了。

實際上,地址這個東西,本來就是一種基本資料型別,本應該在介紹整數、浮點、字元等基本型別的時候把地址顯式地放在一起討論,這樣在後面介紹指標與陣列的時候就能避免許多誤解。可惜不少教材或者根本沒有談及,或者就算提起這個型別也用了指標型別這個字眼。這就錯了,指標不是型別,真正的型別是地址,指標只是儲存地址這種資料型別的變數!打個比方,對於

int i=10;

10是整數,而i是儲存整數的變數,指標就好比這個i,地址就好比那個10。指標能夠進行加減法,原因並不是因為它是指標,加減法則不是屬於指標這種變數的,而是地址這種資料型別的本能,正是因為地址具有加減的能力,所以才使指標作為存放地址的變數能夠進行加減運算。這跟整數變數因為整數能夠進行加減乘除因而它也能進行加減乘除一個道理。

那麼陣列名又應該如何理解呢?用來存放陣列的區域是一塊在棧中靜態分配的記憶體(非static),而陣列名是這塊記憶體的代表,它被定義為這塊記憶體的首地址。這就說明了陣列名是一個地址,而且,還是一個不可修改的常量,完整地說,就是一個地址常量。陣列名跟列舉常量類似,都屬於符號常量。陣列名這個符號,就代表了那塊記憶體的首地址。注意了!不是陣列名這個符號的值是那塊記憶體的首地址,而是陣列名這個符號本身就代表了首地址這個地址值,它就是這個地址,這就是陣列名屬於符號常量的意義所在。由於陣列名是一種符號常量,因此它是一個右值,而指標,作為變數,卻是一個左值,一個右值永遠都不會是左值,那麼,陣列名永遠都不會是指標!不管什麼話,只要說陣列名是一個指標的,都是錯誤的!就象把剛才int i=10例子中的10說成是整數變數一樣,在最基本的立足點上就已經完錯了。

總之要牢牢記住,陣列名是一個地址,一個符號地址常量,不是一個變數,更不是一個作為變數的指標!

在陣列名並非指標這個問題上,通常會產生兩種疑問:

1。作為形參的陣列,不是會被轉換為指標嗎?

2。如果形參是一個指標,陣列名可以作為實參傳遞給那個指標,難道不是說明了陣列名是一個指標嗎?

首先,C語言之所以把作為形參的陣列看作指標,並非因為陣列名可以轉換為指標,而是因為當初ANSI委員會制定標準的時候,從C程式的執行效率出發,不主張引數傳遞時複製整個陣列,而是傳遞陣列的首地址,由被調函式根據這個首地址處理陣列中的內容。那麼誰能承擔這種“轉換”呢?這個主體必須具有地址資料型別,同時應該是一個變數,滿足這兩個條件的,非指標莫屬了。要注意的是,這種“轉換”只是一種邏輯看法上的轉換,實際當中並沒有發生這個過程,沒有任何陣列實體被轉換為指標實體。另一方面,大家不要被“轉換”這個字眼給矇蔽了,轉換並不意味著相同,實際上,正是因為不相同才會有轉換,相同的話還轉來幹嗎?這好比現在社會上有不少人“變性”,一個男人可以“轉換”為一個女人,那是不是應該認為男人跟女人是相同的?這不是笑話麼。

第二,函式引數傳遞的過程,本質上是一種賦值過程。C89對函式呼叫是這樣規定的:函式呼叫由一個字尾表示式(稱為函式標誌符,function designator)後跟由圓括號括起來的`賦值表示式列表組成,在呼叫函式之前,函式的每個實際引數將被複制,所有的實際引數嚴格地按值傳遞。因此,形參實際上所期望得到的東西,並不是實參本身,而是實參的值或者實參所代表的值!舉個例來說,對於一個函式宣告:

void fun(int i);

TAGS:陣列名