iT邦幫忙

0

C語言陣列名稱和指標常數

各位前輩們大家好~
最近在自學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 ??
這之中是否有什麼我理解錯誤的地方呢~

圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 個回答

4
wrxue
iT邦好手 1 級 ‧ 2020-10-25 22:46:15
最佳解答

可以說以你在書上所學的觀念來說,這樣"解釋"是沒錯的,但這只能說明這個語言你理解的不夠深。要了解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]就是aa就是[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是同義的,就交由時間慢慢發酵,之後再回來看也不遲。

原來如此~是一樣的意思!!
非常感謝前輩的熱心指教~!!

我要發表回答

立即登入回答