1. 程式人生 > >你的月亮我的C(六):指標和陣列的那些事

你的月亮我的C(六):指標和陣列的那些事

先來看幾個問題,一邊從問題中入手,一邊看看指標和陣列之間的那些事:

1、char arr[ ]和char *arr是等價的嗎?

答:不是。看下指標和陣列的定義:陣列是一個用同一型別的多個連續元素組成的事先分配好的記憶體塊。指標是一個可以對任何資料元素的引用。所以陣列的定義char arr[ n ]表示申請n個字元記憶體的位置,這塊記憶體的名字為arr,也就是說有一塊名為“arr”的記憶體“塊”,裡面有n個字元的容量。而指標char arr*表示申請一個名為arr的指標,這個指標可以指向任何的地方,或者指向NULL。看下面這張圖或許你會更清楚:

  1. 指標和陣列等價到底是什麼意思?

答:引用Steve Summit的話:“多數的陣列引用都會退化為陣列的第一個元素的指標,這是C語言中指標和陣列“等價”的基礎。”指標和陣列“等價”但並不是說它們相同,指標和陣列指標不能互換。引用Wayne Throop的話:“在C語言中只是指標算術和陣列下標運算等價,指標和陣列是不同的。”

也就是說,當你對陣列進行操作時(其實從你一開始定義一個數組時),編譯器就會生成一個指向陣列第一個元素的指標,這就是上面說的陣列的退化。

  1. 既然指標和陣列不同,為什麼在函式的形參中,指標和陣列宣告可以互換?

答:因為陣列會被馬上退化為指標,所以陣列實際上沒有被傳進去函式裡,函式接收到的其實是一個指標,例如:

Int fun(char arr[ ])

{

}

其實在編譯器中被當作了指標來處理,它等於:

Int fun(char *arr)

{

}

  1. 為什麼不能用“=”給陣列賦值?

char arr[ 10 ];

arr=”abcde”;

答:因為上面所說的,“多數的陣列引用都會被退化為陣列的第一個元素的指標。”所以,你不能把陣列作為一個整體來操作。當你使用一個數組的名稱的時候,你得到的是一個指標而不是陣列。例如arr[ 4 ]其實會被等價於*((arr)+(4)),所以,如果你想把一個數組複製其內容,你可以使用strcpy:

strcpy(arr, “abcde”);

有人會問了,既然不能用“=”給陣列賦值,那麼為什麼下面這段程式碼是可以的?

Int fun(char arr[ ])

{

If (arr[ 0] ==’\0’) {

arr=”justin”;

}

}

因為陣列在做為形參傳進去函式時會被立刻退化成指標呀!上面也說了,陣列實際上沒有被傳進去函式裡,函式接收到的其實是一個指標,所以,在fun函式中形參char arr[ ]被編譯器換成了char *arr指標,所以對於指標操作arr=”justin”是可以的。

  1. 為什麼arr[ 3 ]和3[ arr ]輸出是一樣的?為什麼可以寫3[ arr ]?

答:在C語言中,陣列名和下標是可以互換的,還記不記得上面第4問所說的:“arr[ 4 ]其實會被等價於*((arr)+(4))。”其實,陣列的下標操作符實際上是個指標操作符arr[ 3 ]等價於3[ arr ]。是因為:

arr [ 3 ]=*((arr)+(3));

而*((arr)+(3))=*((3)+(arr));(加法交換律)

所以arr[ 3 ]=3[ arr ]。

  1. 為什麼int arr[ 8 ]; scanf(“%d”, arr);陣列arr前不用加&?

答:我們知道陣列的引用會被退化成指標,所以對陣列arr引用時,等於是生成了一個int型的指標,指向了陣列的第一個元素。而對&arr引用是,等於是生成了一個“8個int型的陣列”的指標,指向整個arr陣列。所以對整個陣列做scanf操作明顯是不行的。

最後總結一下,指標和陣列的那些事:

  1. 陣列是一個用同一型別的多個連續元素組成的事先分配好的記憶體塊。指標是一個可以對任何資料元素的引用。陣列定義後便自動分配空間,但是不能重新分配空間或者說改變空間大小。指標在定義後必須被賦值來指向一個分配好的空間,通常使用malloc。
  2. 指標和陣列並不相同。平常說的指標和陣列“等價”,是因為多數的陣列引用都會退化為陣列的第一個元素的指標,這是C語言中指標和陣列“等價”的基礎。
  3. 陣列下標的操作符[ ]實際上是個指標操作符,所以為什麼指標也可以當作陣列來使用。例如動態陣列分配中:

Int *p=(int*)malloc(100*sizeof(int));

P[ 2 ]=5;

Printf(“%d\n”, p[ 2 ]);

這樣是可以的,把指標申請(指向)一塊記憶體後,指標本質上也就是一個數組。

  1. arr[ 3 ]和3[ arr ]一樣,因為陣列被退化成指標了嘛,就是這樣:

因為:arr [ 3 ]=*((arr)+(3));

而:*((arr)+(3))=*((3)+(arr));(加法交換律)

所以:arr[ 3 ]=3[ arr ]。