各位前輩們大家好~
最近在自學C語言的指標及陣列的的時候,在書上看到如下的範例程式碼
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int i,a[5]={32,16,35,65,52};
printf("a=%p\n",a);
printf("&a=%p\n",&a);
for(i=0;i<5;i++)
printf("&a[%d]=%p\n",i,&a[i]);
system("pause");
return 0;
}
輸出的結果如下
a=0060FEE8
&a=0060FEE8
&a[0]=0060FEE8
&a[1]=0060FEEC
&a[2]=0060FEF0
&a[3]=0060FEF4
&a[4]=0060FEF8
請按任意鍵繼續 . . .
令我不解的地方是,如果說整數陣列a的名稱本身為一個指標常數,其內容為陣列a的第一個元素的位址(也就是0060FEE8),但是此指標常數自己的位址卻也是0060FEE8,那如此一來陣列的第一個元素"整數32"的儲存記憶體不就被重複使用了?換句話說0060FEE8這塊記憶體位址不僅儲存了整數32(&a[0]=0060FEE8),也儲存了自己的位址0060FEE8 ??
這之中是否有什麼我理解錯誤的地方呢~
可以說以你在書上所學的觀念來說,這樣"解釋"是沒錯的,但這只能說明這個語言你理解的不夠深。要了解C語言運作,一定要配合組合語言來看,Visual Studio可以使用這個功能,可以自己上網爬文如何使用。
先來反問一個問題,若陣列a
的名稱如你所說是一個指標,你有試著跑過下面的範例可以成功嗎?為什麼不能成功?
int a[5] = { 32,16,35,65,52 }, b[5] = {0, 0, 0, 0, 0};
a = b;
上面的範例結果當然是無法成功,那再跑下面的試試看?
int a[5] = { 32,16,35,65,52 }, b[5] = { 0, 0, 0, 0, 0 };
int *arrayPointer = a;
printf("&a=%p\n", &a);
printf("arrayPointer=%p\n", arrayPointer);
printf("&arrayPointer=%p\n\n", &arrayPointer);
arrayPointer = b;
printf("&b=%p\n", &b);
printf("arrayPointer=%p\n", arrayPointer);
printf("&arrayPointer=%p\n\n", &arrayPointer);
system("pause");
這個例子當然是可以成功跑的範例,那現在可以想一下,為什麼?兩個差在哪?
差在我有宣告整數指標來存a與b的位址
int *arrayPointer
若照你說的變數a
是一個指標存著&a[0]
這個位址,那為何它不能存&b[0]
這個位址?很奇怪吧?
然而我要告訴你的是,a
並非整數指標變數,反而它就是直接代表一個位址,陣列第一個元素的位址,所以a
(一個位址)與&a
(位址的位址就是位址本人)意義上來說是相同的。
前言都講完了,接下來配合組合語言來看,也許你會更清楚
int a[5] = { 32,16,35,65,52 };
00764E02 mov dword ptr [ebp-28h],20h
00764E09 mov dword ptr [ebp-24h],10h
00764E10 mov dword ptr [ebp-20h],23h
00764E17 mov dword ptr [ebp-1Ch],41h
00764E1E mov dword ptr [ebp-18h],34h
這組合語言大意是,將陣列元素{ 32,16,35,65,52 }
分別存到堆疊[ebp-28h], [ebp-24h], [ebp-20h], [ebp-1Ch], [ebp-18h]
中,[ebp-28h]
存著0x20
(十進位32),而[ebp-28h]
就是a
,a
就是[ebp-28h]
,所以&a
代表取一個位址的位址,就是取位址[ebp-28h]
自己啊!(在你的問題裡,[ebp-28h]
就是0x0060FEE8
)且必須注意,沒有出現將[ebp-28h]
存到任何地方的動作(請對比下方組合語言)
int *arrayPointer = a;
00764E25 lea eax,[ebp-28h]
00764E28 mov dword ptr [ebp-34h],eax
這組合語言大意是,將陣列a
的位址[ebp-28h]
存到堆疊[ebp-34h]
中,然而,[ebp-34h]
就是arrayPointer
的位址(即是&arrayPointer
)!arrayPointer
內的值為陣列a的位址[ebp-28h]
。這是明確的將一個位址存到指標變數內的過程。
到這裡可以清楚了解到,a
直接代表一個位址,不用想成它是一個變數存著一個位址!
但也有可能由於沒學過組合語言,所以一頭霧水,但無妨,只需先記得結論a
與&a
是同義的,就交由時間慢慢發酵,之後再回來看也不遲。