1. 程式人生 > 其它 >陣列與指標的比喻

陣列與指標的比喻

技術標籤:陣列與指標c語言

陣列與指標的比喻

新人小白,初學陣列與指標,想要略談一下兩者的聯絡與區別。

我喜歡用比喻的方式說明問題。

現在,你可以把龐大的電腦記憶體看作一個世界(類似於我的世界),每個方塊都有它的座標,,每個方塊也都有它本身的內容(比如說石頭,草塊,泥土);這就對應著電腦資料內容的兩大要素:資料本身與資料在電腦中的地址。

而陣列可以說是電腦為了宣告一堆資料而在這個世界中建的公寓,一維陣列即為一層公寓,多個房間;二維可以是多層公寓,多個房間;三維就是一個小區了……需要注意的是,這些房子的建設者為了省事兒,把每個房間的大小建設的一樣大,房間大小取決於你的你的宣告,如果你用int宣告,那麼你會得到一堆四個格格大小的房間。

而指標就是電腦資料對應的地址,記錄的就是每個房間的門牌號。對於一個大小隻有四個格格的房間來說,他的門牌號就是第一個格子的座標,對於一整個陣列來說,他的地址就是第一個房間的第一個格子的座標。

需要注意的是,這裡指標加一不是數值加一,而是“門牌號”加一,即直接加了一個房間的格數。如:

#include<stdio.h>
#define SIZE 4
int main()
{
	short dates[SIZE];
	short *pti;
	short index;
	double bills[SIZE];
	double *ptf;
	pti = dates;
	ptf = bills;
printf("%23s %15s\n","short","double"); for(index=0;index<SIZE;index++) printf("pointers+%d: %10p %10p\n",index,pti+index,ptf+index); return 0; }

其輸出結果為:

                  short          double
pointers+0: 000000000062FE00 000000000062FDE0
pointers+1: 000000000062FE02 000000000062FDE8
pointers+
2: 000000000062FE04 000000000062FDF0 pointers+3: 000000000062FE06 000000000062FDF8

明顯的,由於short型別佔用兩個位元組,double型別佔用八個位元組,所以指標加以後分別+2與+8。

上面程式碼中涉及到賦值語句pti=dates。在這裡,dates(陣列名)就代表這整個陣列的“公寓地址”,而這個地址與公寓第一個房間的地址(門牌號)剛好相同,即:

date==&dates[0];

”“&”都是指標運算子,“”找到地址對應的值,“&”找到值對應的地址。

而陣列與指標的聯絡就呼之欲出了,由於陣列名可以表示陣列第一個元素對應的地址,所以陣列的元素均可以使用指標表示。

如下:

dates + 2==&dates[2];//相同的地址
*(dates + 2)== dates[2];//相同的值

同時,陣列與指標也有一定區別。

我們先來看這樣一個程式碼:

//字串的地址 
#define MSG "I`m special" 
#include<stdio.h>
int main()
{
	char ar[]=MSG;
	const char *pt =MSG;
	printf("address of \"I`m special\":%p \n","I`m special" );
	printf("              address ar:%p \n",ar);
	printf("              address pt:%p \n",pt);
	printf("             address MSG:%p \n",MSG);
	printf("address of \"I`m special\":%p \n","I`m special" );
		
	return 0;
}

其輸出結果為:

address of "I`m special":0000000000404000
              address ar:000000000062FE00
              address pt:0000000000404000
             address MSG:0000000000404000
address of "I`m special":0000000000404000

這裡先將字串"Im special"定義為MSG,再分別用陣列與指標研究這個"Im special"。

根據輸出結果發現:表示該字串的指標pt,與表示該字串的陣列ar地址不同!

對此區別,我們要先明白陣列與指標兩種不同的工作原理:

當把這個程式載入記憶體時,也載入了陣列中的字串,而這些字串儲存在靜態儲存區(在這裡為 0000000000404000 這個地址)中。當程式執行時,就會將這些字串拷貝到陣列(在這裡為 000000000062FE00 這個地址)中。注意,這時候字串有兩個副本,一個是在靜態儲存區中,另一個放在陣列中。

這時的陣列名ar就是ar【0】的地址,但指標pt指向的是字串"I`m special" 的原地址。

通俗來講:你現在在這個世界這個世界的野外修了個兵馬俑(字串),用陣列就是建個房子,把兵馬俑的複製品搬到房間裡,對房間裡一個個小兵進行敲打,整容,截肢,為所欲為。而指標就粗暴了,直接殺到野外,對原兵兵進行敲打,整容,截肢,為所欲為……(只是這樣做屬於破壞公物,一般是不被允許的)

那我們開始說區別:

第一,這裡的ar由於表示的是門牌號,所以它是不能亂改的,就像施工工地上的一個大房子不能亂左右橫跳一樣;但指標pt不一樣,他只是通向兵馬俑的地址,一個數字而已,可以對他進行pt++等運算。

第二,由於陣列地址的不可更改性,ar只能做右值,不能做左值,就像只能X=3不能3=X一樣;但指標可以做左右值。

第三,陣列的元素是變數,所以我們可以對ar【0】或*(ar+0)進行修改,但指標指向的是公物!前面提到,編譯器可以用記憶體中的一個副本表示所有完全相同的字串字面量,運用指標改變字串中內容,即改變了所有相同字串的內容,舉個栗子:

char *p = "Klingon";
p[0]='F';//ok?
printf("Klingon");//一號位
printf(": Beware the %ss!\n","Klingon") ;//二號位

編譯器可能不允許這樣做,也可能允許,但即使可以,對於當前C標準來說,這樣做是未被定義的。

下面我們假設他可以編譯成功,執行後輸出結果將如下:

Flingon: Beware the Flingons!

注意,程式碼中的一二號位Klingon都被列印成了Flingon!

就是說,如果我們用指標把“I love you”改成“I hate you”,那我可能永遠都說不出我愛你了!即使打出我愛你,打印出來的也可能是我恨你。

所以,建議在把指標初始化為字串字面量時使用const限定符,就像這樣:

const char *p="I love you";  //推薦用法

願你的愛生生世世不變質!

好了,謝謝觀看,就先寫這麼多了,拜拜。

(參考第六版C Primer Plus完成)