前一章節講了許多,接下來要進入多維陣列了,不過相信你很快就能適應了。
簡單來說,int (*p)[MaxN]
是「指向一個含有 MaxN
個 int
的陣列」的指標。
假設有一個二維陣列:
int arr[MaxM][MaxN];
arr
本身在某些表達上會轉換成 int (*)[MaxN]
,也就是指向 arr[0]
(第一列)的指標。現在若我們有:
int (*p)[MaxN];
p = arr; // p現在指向arr[0],也就是arr的第一列
p
的型別:int (*p)[MaxN]
p
是一個指標,指向「包含 MaxN
個int
的陣列」。int [MaxN]
」型態的陣列,所以現在*p
類似於一維陣列的名稱功能。p
是什麼?p
目前可被視為 p
所指向的第一整列(row)。也就是 arr[0]
這個一維陣列(大小為 MaxN
)。p
解參考一次的話,上面說到*p
類似於一維陣列的名稱功能。所以現在*p
表示指向arr[0]
這一陣列的第一個元素的位址。可以說是指到arr[0][0]
這個位址。(*p)[i]
:(*p)[i]
表示從 p
(也就是 arr[0]
) 開始,取第 i
個元素。(*p)[i]
等同於 arr[0][i]
(為一個 int)。p
進行指標運算,如 p + 1
:p + 1
會跳到下一列,也就是 arr[1]
。p + 1
) 是 int (*)[MaxN]
型別的值,指向 arr[1]
。(*(p + 1))[i]
= arr[1][i]
**p
:arr[0][0]
的內容**(p+1)
代表arr[1][0]
的內容*(*p+2)+1)
代表arr[2][1]
的內容從上面我們還可以總結出,二維陣列名稱和名稱解參考一次都會輸出位址、而解參考兩次會輸出內容。
你可以這樣記: 要得到內容的話,幾維就解參考幾次。
範例:
#include <stdio.h>
int main() {
const int MaxM = 3;
const int MaxN = 4;
int arr[3][4] = {
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12}
};
// p 是一個指標,指向一個擁有MaxN個int的陣列,即 p的型態為 int (*p)[MaxN]
int (*p)[MaxN] = arr; // 指向arr[0]這一行
// 現在 p 等同於 arr[0] (第一列)
// (*p)[0] = arr[0][0] = 1
// (*p)[1] = arr[0][1] = 2
printf("(*p)[0] = %d\n", (*p)[0]); // 輸出 1
printf("(*p)[1] = %d\n", (*p)[1]); // 輸出 2
// 將p往後移動一列
p = p + 1;
// 現在p指向arr[1]
// (*p)[0] = arr[1][0] = 5
// (*p)[1] = arr[1][1] = 6
printf("(*p)[0] = %d\n", (*p)[0]); // 輸出 5
printf("(*p)[1] = %d\n", (*p)[1]); // 輸出 6
// 我們也可以用迴圈走訪整個2維陣列
// 將p重新指回arr
p = arr;
for (int i = 0; i < MaxM; i++) {
for (int j = 0; j < MaxN; j++) {
// p+i 指向 arr[i], (* (p+i))[j] = arr[i][j]
printf("%d ", (*(p+i))[j]);
//printf("%d ", *(*(p+i)+j)); 相同效果
//printf("%d ", *(*(arr+i)+j)); 相同效果
//printf("%p ", *(p+i)+j); 相當於arr[i][j]的位址
}
printf("\n");
}
return 0;
}