首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C >> C 語言基礎

C 語言基礎教程(二):陣列與指標的深度關係——等價性、差異與實務互換技巧

     編輯:C 語言基礎

核心論點:陣列名「退化」為指標,但兩者本質不同

在大多數表達式中,陣列名 a 會隱性轉換為指向首元素的指標 &a[0] (型別 T*),這就是所謂的「退化」。但陣列名不是指標變數,關鍵差異在於:

特性陣列 int a[10]指標 int *p
儲存空間編譯期配置 10*sizeof(int) 位元組僅配置指標本身 (4/8 bytes)
可修改性常量,不可賦值 a = p;、a++變數,可賦值、算術、遞增
sizeof整個陣列大小 (如 40 bytes)指標大小 (4/8 bytes)
&a 型別int (*)[10] (指向陣列的指標)int ** (指向指標的指標)
函數參數退化為 int*,sizeof 失效原本就是 int*

互換等價表達式 (退化後)

設 int a[10]; int *p = a; (p 指向 a[0]):

陣列寫法指標寫法含義
a[i]*(p + i)第 i 元素值
&a[i]p + i第 i 元素位址
a + ip + i指向第 i 元素的指標

指標亦可用下標:p[i] 等價 *(p+i),編譯器產生相同機器碼。

實務範例:字串處理


char s[30], *p;
p = s;                 /* p 指向 s[0] */
p[8] = 'X';            /* 修改 s[8] */
*(p + 8) = 'Y';        /* 同樣修改 s[8] */
p += 5;                /* p 指向 s[5] (指標可算術) */
/* s += 5;  錯誤:陣列名不可修改 */

動態配置 vs 靜態陣列

  • 靜態/自動陣列:char s[30]; 編譯器自動配置/釋放,大小固定。
  • 動態指標:char *p = malloc(30); 執行期決定大小,需手動 free。
  • 兩者在「指向有效記憶體」後,操作介面完全一致 (p[i], *(p+i))。

多維陣列與指標的複雜關係


int a[3][4];           /* 3 列、4 行 */
int (*p)[4] = a;       /* p 指向「含 4 個 int 的陣列」 */

/* 正確用法 */
p[1][2] = 99;          /* 等價 a[1][2] = 99 */
*(p[1] + 2) = 99;      /* 同 */
*(*(p + 1) + 2) = 99;  /* 同 */

/* 錯誤 */
int *q = a;            /* 型別不合:a 退化為 int(*)[4],非 int* */
int **r = a;           /* 更錯 */

函數參數傳遞:退化陷阱


void f1(int a[10]) { /* 實為 void f1(int *a) */ }
void f2(int a[][4]) { /* 保留行大小,實為 void f2(int (*a)[4]) */ }
void f3(int (*a)[4]) { /* 明確指標陣列型別 */ }

/* 呼叫端 */
int m[3][4];
f1(m);      /* 警告:int(*)[4] → int* 丟失行資訊 */
f2(m);      /* 正確 */
f3(m);      /* 正確 */

最佳實務總結

  1. 區分「陣列物件」與「指標值」:宣告即物件,使用多為指標值。
  2. 函數參數首選指標語法:void f(int *a, size_t n) 明確表達「指標+長度」契約。
  3. 多維陣列傳遞保留行大小:void f(int (*a)[4], int rows)。
  4. 需要可修改緩衝區用陣列,需動態大小用指標+malloc。
  5. 啟用 -Warray-bounds、-Wpointer-arith 靜態分析。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved