匯編角度分析 c 語言中指針與數(shù)組的區(qū)別
數(shù)組與指針是兩個不同的概念,即使是從編譯的層面上來看。不過,訪問和操作數(shù)組的行為和指針在用法上極為相似。
數(shù)組的首地址與指針的值,可以認為等同,編譯器能直接得到數(shù)組的首地址, 但要得到指針的值, 必須先得到指針的地址.從而, 通過指針訪問數(shù)組通常要慢一點,當然是
lea (a), %esi /* this is a */ mov (%esi), %eax /* this is a[0] */ 或更簡單的: mov (a), %esi /* this is a[0] */
微不足道的.
對于指針,
int *p;
p 是一個變量,所以編譯器要為之分配一個空間。
.comm p, 4
對于數(shù)組:
int a[10]
a 是一個地址,編譯器會為數(shù)組 a 分配一個空間,但不會為 a 本身分配空間,在使用到a的地方,會被替換為一個地址+屬性,其結(jié)果為一個"常量指針"。
.comm a, 40
lea (p), %esi /* this is &p */ mov (%esi), %edi /* this is p */ mov (%edi), %eax /* this is p[0] */ 或者,更簡單的 mov (p), %esi /* this is p */ mov (%esi), %eax /* and this is p[0] */
相比之下,數(shù)組的引用
int a[10]; a[0];
則省去了取 a 地址的過程,符號 a 代表一個地址,這個地址不存放在任何變量中!
lea (a), %esi /* this is a */ mov (%esi), %eax /* this is a[0] */ 或更簡單的: mov (a), %esi /* this is a[0] */
摘錄二:數(shù)組名、指針、地址這幾個概念的輪回解析
數(shù)組是指針的基礎(chǔ),多數(shù)人就是從數(shù)組的學習開始指針的旅程的。下面我節(jié)選一些在各種論壇和文章里經(jīng)常見到的關(guān)于數(shù)組的文字: “一維數(shù)組是一級指針” “二維數(shù)組是二級指針” “數(shù)組名可以作為指針使用” “數(shù)組名就是..........的常量指針” “數(shù)組名就是..........的指針常量” .................................. 這些文字看起來非常熟悉吧?類似的文字還有許多,或許你就是經(jīng)常說這些話的人呢。不過非常遺憾,這些文字都是錯誤的,實際上數(shù)組名永遠都不會是指針!這個結(jié)論也許會讓你震驚,但它的確是事實。
數(shù)組名、指針、地址這幾個概念雖然是基礎(chǔ)中的基礎(chǔ),但它們恰恰是被混淆和濫用得最多的概念,把數(shù)組名說成指針,是一個概念性的錯誤,實質(zhì)是混淆了指針與地址兩個概念的本質(zhì)。俗話說得好:淺水淹死人。因此,在討論數(shù)組之前,有必要先回過頭來澄清一下什么是指針,什么是地址,什么是數(shù)組名。 指針是C語言具有低級語言特征的最直接的證據(jù)。在匯編語言里面,指針的概念隨處可見。比如SP,SP寄存器又叫堆棧指針,它的值是地址,由于SP保存的是地址,并且SP的值是不斷變化的,因此可以看作一個變量,而且是一個地址變量。地址也是C語言指針的值,C語言的指針跟SP這樣的寄存器雖然不完全一樣,但原理卻是相通的。C語言的指針也是一種地址變量,C89明確規(guī)定,指針是一個保存對象地址的變量。這里要注意的是,指針跟地址概念的不同,指針是一種地址變量,通常也叫指針變量,統(tǒng)稱指針。而地址則是地址變量的值。
看到這里,也許你會覺得,這么簡單的東西還用你來說嗎?的確,對于p與&p來說,99%的人都能在0.1秒內(nèi)脫口而出誰是指針,誰是地址,但是,又有多少人在使用指針的過程中能夠始終如一毫不動搖地遵循這兩個概念呢?不少人使用指針的時候就會自覺或不自覺地把指針和地址兩個概念混淆得一塌糊涂了,數(shù)組名的濫用就是一個活生生的例子。這一點甚至連一些經(jīng)典著作也沒能避免。
不過也不能全怪你自己,筆者認為某些國內(nèi)教材應(yīng)該承擔最大的責任。這些教材一開始就沒有給讀者好好地分清指針與地址的區(qū)別,相反還在講述的過程中有意無意地混用這兩個概念。更有甚者,甚至在書中明言指針就是地址!說這話的家伙最應(yīng)該在C語言這個地圖上抹掉,呵呵。兩個月前我在購書中心隨手翻開了某個作者主編的一本被冠以國家“十五”規(guī)劃重點研究項目的書,書里就是這么寫的。當時筆者就感慨:不知道又要有多少人的思想被這家伙“強奸”了。
實際上,地址這個東西,本來就是一種基本數(shù)據(jù)類型,本應(yīng)該在介紹整數(shù)、浮點、字符等基本類型的時候把地址顯式地放在一起討論,這樣在后面介紹指針與數(shù)組的時候就能避免許多誤解。可惜不少教材或者根本沒有談及,或者就算提起這個類型也用了指針類型這個字眼。這就錯了,指針不是類型,真正的類型是地址,指針只是存儲地址這種數(shù)據(jù)類型的變量!打個比方,對于 int i=10; 10是整數(shù),而i是存儲整數(shù)的變量,指針就好比這個i,地址就好比那個10。指針能夠進行加減法,原因并不是因為它是指針,加減法則不是屬于指針這種變量的,而是地址這種數(shù)據(jù)類型的本能,正是因為地址具有加減的能力,所以才使指針作為存放地址的變量能夠進行加減運算。這跟整數(shù)變量因為整數(shù)能夠進行加減乘除因而它也能進行加減乘除一個道理。
那么數(shù)組名又應(yīng)該如何理解呢?用來存放數(shù)組的區(qū)域是一塊在棧中靜態(tài)分配的內(nèi)存(非static),而數(shù)組名是這塊內(nèi)存的代表,它被定義為這塊內(nèi)存的首地址。這就說明了數(shù)組名是一個地址,而且,還是一個不可修改的常量,完整地說,就是一個地址常量。數(shù)組名跟枚舉常量類似,都屬于符號常量。數(shù)組名這個符號,就代表了那塊內(nèi)存的首地址。注意了!不是數(shù)組名這個符號的值是那塊內(nèi)存的首地址,而是數(shù)組名這個符號本身就代表了首地址這個地址值,它就是這個地址,這就是數(shù)組名屬于符號常量的意義所在。
由于數(shù)組名是一種符號常量,因此它是一個右值,而指針,作為變量,卻是一個左值,一個右值永遠都不會是左值,那么,數(shù)組名永遠都不會是指針!不管什么話,只要說數(shù)組名是一個指針的,都是錯誤的!就象把剛才int i=10例子中的10?黨墑欽淞懇謊謐罨鏡牧⒆愕閔暇鴕丫甏砹恕? 總之要牢牢記住,數(shù)組名是一個地址,一個符號地址常量,不是一個變量,更不是一個作為變量的指針!

浙公網(wǎng)安備 33010602011771號