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

C語言陣列與指標互操作深度解析:本質同一、操作等價

     編輯:關於C語言

C語言陣列與指標互操作深度解析:本質同一、操作等價

C 語言中「陣列名在大多數表達式中退化為指向首元素的指標」是核心觀念。本文從記憶體模型、指標算術、多維陣列實際結構、函數參數傳遞等面向,系統闡述陣列與指標的等價與差異,並提供實戰操作模式與避坑指南。

核心觀念:陣列名 ≠ 指標變數

int a[10];
int *p = a;   // ✅ a 退化為 int* (指向 a[0])
// a = p;     // ❌ 錯誤:a 非左值,不可賦值
// a++;       // ❌ 錯誤:a 非常數指標,不可遞增

差異關鍵:

  • sizeof(a) = 陣列總位元組數 (40);sizeof(p) = 指標大小 (4/8)。
  • &a 型別為 int (*)[10] (指向整個陣列的指標);&p 為 int**。
  • 陣列名**不是**變數,無儲存位置,編譯期即解析為位址常數。

指標算術與陣列索引完全等價

對指向陣列元素的指標 p:

  • p + i 指向第 i 個元素 (位址 + i * sizeof(*p)),**非**單純位址 + i。
  • *(p + i) ≡ p[i] ≡ a[i] ≡ i[a] (利用加法交換律)。
  • p[i] 定義即為 *(p + i),故 i[p] 合法但不建議使用。
int a[12];
int *p = a;
p = a;        // p 指向 a[0]
p = p + 1;    // p 指向 a[1]
p++;          // p 指向 a[2]
// 等價寫法
a[2] = 10;
*(a + 2) = 10;
p[-1] = 5;    // 修改 a[1] (指標減法合法,前提在陣列範圍內)

二維/多維陣列實為「陣列的陣列」

int week[7][24]; // 7 個元素的陣列,每元素為 int[24]
  • week 退化為 int (*)[24] (指向含 24 個 int 陣列的指標)。
  • week[i] 退化為 int* (指向第 i 列首元素)。
  • week[i][j] ≡ *(week[i] + j) ≡ *(*(week + i) + j)。
  • 記憶體佈局:**列優先** 連續儲存,week[0][23] 緊接著 week[1][0]。

指向多維陣列的指標宣告與操作

int (*p)[24] = week; // p 指向 int[24] 類型
p++;                 // 移動到下一列 (位址 + 24*sizeof(int))
int val = p[2][3];   // 等價 week[3][3] (p 為 week+1 時)

錯誤示範:int **p = week; ❌ 型別不相容,week 非指標陣列。

函數參數傳遞:陣列退化為指標

void func(int a[10]);      // 等價 void func(int *a);
void func(int a[][24]);    // 必須指定次維度大小
void func(int (*a)[24]);   // 明確指標宣告,同上

實戰建議:

  1. 函數參數**一律使用指標宣告** (int *a 或 int (*a)[N]),避免陣列語法誤導。
  2. 同時傳遞長度參數:void func(int *a, size_t n)。
  3. 需修改呼叫端指標本身時,傳遞二級指標:void alloc(int **p, size_t n) { *p = malloc(n * sizeof(int)); }。

動態配置多維陣列三種模式

模式配置方式存取語法記憶體連續性適用場景
指標陣列int **p = malloc(r * sizeof(int*)); for(i) p[i] = malloc(c * sizeof(int));p[i][j]各列分離列長不固定、需逐列釋放
單一區塊 + 指標陣列int *buf = malloc(r*c*sizeof(int)); int **p = malloc(r*sizeof(int*)); for(i) p[i] = buf + i*c;p[i][j]完全連續高效存取、單次釋放
VLA (C99)void func(int r, int c) { int a[r][c]; }a[i][j]堆疊連續小規模、自動釋放、C11 為選擇性

常見陷阱與避坑指南

  1. 字串常值指標:char *s = "abc"; 應為 const char *s,寫入導致 UB。
  2. 陣列作為結構體成員:struct { int a[10]; } s; 可整體複製 (s1 = s2),但 int *p 成員僅複製指標 (淺拷貝)。
  3. sizeof 陷阱:函數參數 void f(int a[10]) { sizeof(a); } 回傳指標大小,非陣列大小。
  4. 指標減法:僅定義於**同一陣列**內兩指標,結果為 ptrdiff_t (元素個數差)。

現代 C 實務建議

  • 優先使用 std::vector (C++) 或 malloc+長度參數 (C) 管理動態陣列。
  • 固定大小陣列改用 struct { int data[N]; } 封裝,獲得整體複製語意。
  • 介面設計採用 void func(const int *data, size_t len) 唯讀、`void func(int *data, size_t len)` 讀寫。
  • 避免多層指標 (int ***) ,改用扁平化索引 data[i * stride + j]。

結語:陣列與指標在 C 語言中「本質同一、操作等價」,關鍵在於理解**退化規則**、**指標算術以元素大小為單位**、以及**多維陣列實為巢狀陣列**。掌握這三點,即能靈活駕馭記憶體、撰寫高效且安全的 C 程式碼。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved