第四章 [ ]運算符的本質

 

數組是存在於人們頭腦中的一個邏輯概念,而編譯器其實並不知道有數組這個東西,它所知道的,只是[]運算符,當遇到[]運算符的時候,編譯器只是簡單地把它轉換爲類似*(*(a+i)+j)這樣的等價表達式,之所以是這種表達式,如前幾章所述,是因爲C語言的數組實現本質上是數組的嵌套。

        由於這種等價關係的存在,會產生一些古零精怪的表達式,例如:

10[a]

這個表達式初看上去讓人摸不着頭腦,它是什麼呢?如上所述,編譯器會把它轉換爲*(10+a),把a和10調換一下,就是*(a+10)了,這個就是a[10]。

[]運算符之前還可以是一個表達式,例如:(10+20)[a]。

嚴格來講,以上兩個表達式是非法的,因爲C89對於數組的引用(注意不是數組定義)規定:帶下標的數組引用後綴表達式由一個後綴表達式後跟一個括在方括號中的表達式組成。方括號前的後綴表達式的類型必須爲“指向T類型的指針”,其中T爲某種類型;方括號中表達式的類型必須爲整型。這個規定說明,進行數組引用的時候,[]運算符的左邊並非必須爲數組名,而可以是一個表達式,但這個表達式的類型必須爲“指向某類型的指針”。顯然10跟(10+20)連地址都不是,因此實際上他們是非法的,編譯器在這裏並沒有嚴格遵守標準的規定。但如果是:

int a[10], *p = a;

(p+1)[2]這樣就是合法的,因爲p+1的結果仍然是一個指針。

要注意的是,雖然後綴表達式是一個“指向某類型的指針”,但不要被這裏所說的指針一詞搞混了,上面的規定不能反過來使用。還是以上面的例子爲例,我們可以p[i]這樣使用p,這是符合上述規定的,但並不能因爲指針p能夠以p[i]這種形式使用就認爲p是一個數組,這就錯誤了,不能反過來應用上述規則。

        最後說一下編譯器對&*的優化,對於數組int a[10],如果對其中一個元素取地址,例如&a[1],這條表達式等價於&*(a+1),編譯器並不會先計算*再運算&,而是對&*兩個運算符進行優化,把它們同時去掉,因爲兩者的作用是相反的,最後得到計算的是a+1表達式。

發佈了23 篇原創文章 · 獲贊 0 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章