C/C++陣列取值的真實實現——一個初學者的常見疑惑
阿新 • • 發佈:2020-08-12
頭條稽核了兩個小時都沒稽核完,先發到這裡了。
第一部分
剛剛看到西芬探測資深軟體工程師@快樂的老碼農 分享了一個微頭條:
相信這位作者是肯定清楚箇中原因的,只是丟擲來讓大家討論。評論區裡有許多朋友顯然是不瞭解的:
還有很多,就不一一截圖了。
毛主席說“沒有調查就沒有發言權”,我們還能看到有信口開河的朋友:
終於有一位朋友給出了正確答案,但是可惜的是,這個和彙編沒關係。
下面我們來說一說這到底是怎麼回事。
第二部分
我們直接看Stack Overflow上面這個2008年提出的問題:
然後看看大神的解答:
這下大家該明白了吧?
對的,C/C++中對陣列取值a[i]的實現,是*(a+i)。你寫i[a],得到是*(i+a),結果是一模一樣的。
第三部分
關於原因,就像這位網友說的一樣,在C語言誕生的年代,計算資源並不像我們現在這樣豐富,64KB的記憶體就已經算是很大了。在這種情況下,C語言編譯器不會去做很多的語法檢查,而是簡單的把x[y]給翻譯成*(x+y).
第四部分
再簡單說一下評論區裡關於組合語言是不是這樣寫的爭論:
沒錯,通常在彙編中,你需要自己指定“真正”的地址偏移量。不過組合語言有非常非常多種,所以我也不知道會不會有一種組合語言不用這樣做,不過我估計是沒有的。
第五部分
這部分是給對C語言指標不熟悉的朋友準備的。看如下程式碼:
int a[5];
我們取a[2],編譯器翻譯成*(a+2)。有人會說,這怎麼能行呢?
這就是在第四部分說的C語言區別於彙編的特性。a是一個數組,在這裡被看成一個int型別的指標,對它進行+操作,實際上a的偏移量不是2,而是2*sizeof(int),在一般的32位機器上是2*4=8。
這就是說,如果一個int的指標p指向0x1230,那做p+2,得到的不是0x1232而是0x1238.