C 語言中,數組元素的訪問不僅限於下標法。以下三種寫法完全等價:
int a[] = {3,4,5,6,7,3,7,4,4,6};
// 1. 下標法
for (int i = 0; i < 10; i++) printf("%d", a[i]);
// 2. 數組名 + 偏移量解引用
for (int i = 0; i < 10; i++) printf("%d", *(a + i));
// 3. 指針變量 + 下標法
int *pa = a;
for (int i = 0; i < 10; i++) printf("%d", pa[i]);
// 4. 指針變量 + 偏移量解引用
for (int i = 0; i < 10; i++) printf("%d", *(pa + i));
從語法形式看,數組名 a 與指針變量 pa 幾乎可以互換。但這真的是完全一樣嗎?
請看下面的代碼:
int *pa, a[] = {3,4,5,6,7,3,7,4,4,6};
pa = a;
for (int i = 0; i < 10; i++) {
printf("%d", *pa);
pa++; // ✅ 合法:指針變量可修改
}
若將 pa++ 改為 a++,編譯將報錯。原因在於:
pa):可讀可寫,值可修改a):指針常量,值不可修改,始終指向數組首元素const 定義指針常量int a[] = {3,4,5,6,7,3,7,4,4,6};
int * const pa = a; // const 在 * 之後:pa 是常量指針
for (int i = 0; i < 10; i++) {
printf("%d", *pa);
pa++; // ❌ 編譯錯誤:pa 為常量,不可修改
}
此時 pa 與數組名 a 行為完全一致,進一步證明數組名本質是指針常量。
int * const a = {...} 不合法?數組初始化語法 int a[] = {...} 是編譯器特殊處理的,它同時完成內存分配、初始化並將 a 綁定為該內存塊的常量標識符。無法用指針常量語法替代。
| 特性 | 數組名 a | 指針變量 pa |
|---|---|---|
| 本質 | 指針常量 | 指針變量 |
| 值可否修改 | 不可 | 可 |
| 指向內存 | 固定數組首地址 | 可指向任意同類型地址 |
| sizeof 結果 | 整個數組大小 | 指針大小(4/8 字節) |
| 作為函數參數 | 退化為指針 | 直接傳遞地址值 |
sizeof、& 外)會退化為指向首元素的指針++、--、+n)的步長由指向類型的大小決定,這對數組遍歷至關重要徹底理解「數組名 ≠ 指針變量」,是避免 C 語言中常見指針錯誤的基石。