若指標 pa 指向陣列元素 a[0],則:
pa + 1 指向 a[1]pa + i 指向 a[i]*pa 等價於 a[0]*(pa + i) 等價於 a[i]C 語言編譯器內部正是透過指標運算實現下標訪問:a[i] 在編譯期轉換為 *(a + i)。因此下標與指標在語義上完全等價。
int score[10] = {76, 85, 90, 67, 59, 79, 82, 95, 91, 65};
int length = sizeof(score) / sizeof(score[0]);
for (int i = 0; i < length; i++) {
printf("%d\n", *(score + i)); // 陣列名 score 即首元素地址
}
輸出:76 85 90 67 59 79 82 95 91 65
將陣列名傳給函數時,實際傳遞的是首元素地址。因此函數參數必須聲明為指標:
// 以下三種聲明等價 void func(int *arr); void func(int arr[]); void func(int arr[10]); // 10 被忽視,退化為指標
函數內部無法獲知陣列長度,必須額外傳遞長度參數。
int strlen(char *s) {
int n;
for (n = 0; *s != '\0'; s++)
n++;
return n;
}
關鍵點:
s 是指標變數,可合法自增(s++)char s[],則 s++ 非法(陣列名非常量指標)指標加減運算的步長由指向類型大小決定:
int *p:p+1 增加 sizeof(int) 位元組char *p:p+1 增加 1 位元組double (*p)[5]:p+1 增加 5*sizeof(double) 位元組這正是 *(a + i) 能正確定位第 i 個元素的根本原因。
| 誤區 | 正確理解 |
|---|---|
| 陣列名就是指標 | 陣列名是常量指標,不可修改;指標是變數 |
| 函數接收陣列參數能用 sizeof 求長度 | 參數退化為指標,sizeof 只得指標大小(4/8 位元組) |
| 指標自增是加 1 位元組 | 步長 = 指向類型大小 |