陣列名和指標的區別

2021-06-21 09:29:59 字數 3624 閱讀 9217

//**  :

近段時間在整理自己大學幾年來學習c++的點點滴滴,寫這篇文章源於看林銳博士的《高質量c++指南》時,看到文章直接把指標和陣列名視為同一東西,原文為「陣列名本身就是乙個指標,是乙個指標常量,即a等價於int * const a,因此你不能試圖修改陣列名的值」,摘自第三版127頁第7.2.1小節。

自己初學c++時也被陣列和指標搞得昏頭轉向過,通過多方求證和對比實驗已把指標和陣列弄得稍明白,但是今天又看到乙個人說「陣列名就是指標」這樣的言論,我就有這個想法把自己對指標和陣列名的理解寫出來,我不敢說我的理解是正確的,但是,至少沒那麼徹底的禍害人。

陣列名絕對不等於指標,而且不是指標,這是我的觀點

首先看c標準對指標的解釋為:指標是乙個變數,變數的值是另外乙個變數的位址。那麼,既然指標是變數,那麼指標必然有自己的儲存空間,只不過是該儲存空間內的值是乙個位址值,而不是別的內容。如果按照林博士的觀點「陣列名就是指標」,想必,陣列名也會是乙個變數,而且有自己的儲存空間?下面上彙編**反駁之,彙編**沒有騙我們,陣列名僅僅是乙個符號,不是變數,它沒有自己的儲存空間,而指標實實在在的是個變數,有自己的空間:

下面是c++**:

[cpp]view plain

copy

#include 

using

namespace

std;  

intmain()    

這段**的目的是通過4個對比實驗逐一證明指標和陣列名不是用乙個東西,請看下面的彙編**便可一目了然,每個對比實驗的結果都能說名:陣列名不是指標,它就是乙個符號。

[plain]view plain

copy

6:        int i = 10;  

00401048   mov         dword ptr [ebp-4],0ah    //(1)  

7:        int *pi = &i;  

0040104f   lea         eax,[ebp-4]             

00401052   mov         dword ptr [ebp-8],eax    //(2)  

8:  

9:        int a[2];      

10:       a[0] = 5;  

00401055   mov         dword ptr [ebp-10h],5 //(3)  

11:       a[1] = 15;  

0040105c   mov         dword ptr [ebp-0ch],0fh  

12:  

13:       int *pa = a;    

00401063   lea         ecx,[ebp-10h]            //(4)  

00401066   mov         dword ptr [ebp-14h],ecx  

14:       pa = a+1;  

00401069   lea         edx,[ebp-0ch]           //(5)  

0040106c   mov         dword ptr [ebp-14h],edx  

15:  

16:       int j = a[0];   

0040106f   mov         eax,dword ptr [ebp-10h]  //(6)  

00401072   mov         dword ptr [ebp-18h],eax  

17:       int k = *pa;  

00401075   mov         ecx,dword ptr [ebp-14h]  

00401078   mov         edx,dword ptr [ecx]  

0040107a   mov         dword ptr [ebp-1ch],edx  

18:  

19:       //++a;          

20:       ++pa;  

0040107d   mov         eax,dword ptr [ebp-14h]  //(7)  

00401080   add         eax,4  

00401083   mov         dword ptr [ebp-14h],eax  

21:  

22:       return 0;  

00401086   xor         eax,eax  

23:  

24:   }  

簡單學過彙編的人都基本能看懂上面的**,下面逐一分析(1)-(7)的彙編**告訴我們的事實:

(1)、i是個整型變數,可以看出編譯器為i分配了空間,位址為ebp-4

(2)、先lea取i的位址,然後存入到ebp-8的空間中,這就是pi的位址,足矣證明pi是個變數,有自己的空間

(3)、重點之處,定義了乙個陣列,但是,彙編**告訴我們,編譯器只給a[0]和a[1]分配了記憶體空間,a[0]的位址為:ebp-10,a[1]為:ebp-0c,卻沒有給,陣列名a也分配空間,這裡起碼可以斷定陣列名a不是乙個變數只是個符號

(4)、從**lea ecx,[ebp-10h]可以看出,ebp-10是a[0]的位址,對陣列名a的引用已經被替換為對陣列首元素的位址了

(5)、a+1的彙編**也是程式設計了對ebp-0c位址單元的引用,而這個位址是a[1]的位址,更進一步說明了問題

(6)、是為了對比,對陣列的引用和對指標的引用不同之處,通過下面三行彙編**可以看出:

17:       int k = *pa;

00401075   mov         ecx,dword ptr [ebp-14h]

00401078   mov         edx,dword ptr [ecx]

0040107a   mov         dword ptr [ebp-1ch],edx

對指標pa的引用是乙個間接訪問,epb-14h是pa的位址,而mov ecx,dword ptr [ebp-14h]是先取得pa的位址,然後[ecx]取該位址中的內容,並mov到ebp-1c中,改記憶體就是變數k的記憶體空間首位址,這樣就完成了對pa的引用

(7)這個是重點分析的地方,很對多人對於陣列名就是指標持贊同觀點的乙個冠冕堂皇的證據是「

陣列名不能被修改,因為陣列名是乙個常量指標

」,也就是不能執行 a = a+1;這句話對一般,錯一半,對的是,陣列名確實不能被修改,錯的是,不能被修改的原因不是因為陣列名是常量指標,而是因為陣列名只是乙個符號,不是乙個變數,因此不能作為乙個左值,因此不能被修改,這裡又涉及到左值和右值的問題,就不再贅述,網上資料很多。

通過上述幾個對比實驗,能夠非常清晰的看到,陣列名和指標的本質區別:指標是乙個變數,有自己對應的儲存空間,而陣列名僅僅是乙個符號,不是變數,因而沒有自己對應的儲存空間,到此已經可以得出結論,「陣列名永遠不等於指標」。

我認為,林博士的意思是說,陣列名和指標在參與表示式運算時效果是一樣的,但是不能簡單粗暴的說兩者是相等的

上述如有錯誤之處,懇請指出,我必會虛心聽取,認真論證修改,以免更多的人困惑

陣列名和指標區別

前兩天同學問了我乙個問題 陣列名和指標有什麼區別,或者說這兩者有沒有區別?我回顧了下,大學課堂上老師講的,貌似記得老師說陣列名就相當於指標,比如 一維陣列就是一級指標 二維陣列是二級指標 之類的。結果同學告訴說原來我也是這麼理解的,其實 陣列名與指標有著本質的區別 然後給我推薦了一篇博文。我們經常見...

陣列名和指標的區別

魔幻陣列名 請看程式 本文程式在win32平台下編譯 1.include 2.int main int argc,char argv 3.size 3 1 陣列名不是指標 size 我們先來推翻 陣列名就是指標 的說法,用反證法。證明 陣列名不是指標 假設 陣列名是指標 則 pstr和str都是指標...

陣列名和指標的區別

引言 指標是c c 語言的特色,而陣列名與指標有太多的相似,甚至很多時候,陣列名可以作為指標使用。於是乎,很多程式設計者就被搞糊塗了。而許多的大 學老師,他們在c語言的教學過程中也錯誤得給學生講解 陣列名就是指標 很幸運,我的大學老師就是其中之一。時至今日,我日復一日地進行著c c 專案的開發,而身...