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

C 語言「數組指針」與「指針數組」徹底區分:定義、記憶體佈局、二維數組應用

     編輯:關於C語言

C 語言「數組指針」與「指針數組」徹底區分

這兩個概念僅一字之差,卻是 C 指針進階的分水嶺。本文從語法解析、記憶體模型、二維數組綁定、常見面試陷阱四個維度,一次講透。

核心定義對比

名稱聲明語法語法結合優先級本質佔用空間
數組指針
(Array Pointer / Row Pointer)
int (*p)[N];() 優先 → p 是指針 → 指向 int[N]單一指針變量1 個指針大小
指針數組
(Pointer Array)
int *p[N];[] 優先 → p 是數組 → 元素類型 int*N 個指針組成的數組N 個指針大小

記憶體佈局圖解

// 數組指針:單一指針 → 指向整個二維數組首行
int a[3][4];
int (*p)[4] = a;     // p 指向 a[0] (即 &a[0][0])
p + 1;               // 跨越 4 個 int,指向 a[1]

// 指針數組:3 個獨立指針 → 分別指向各行
int *q[3];
for (int i = 0; i < 3; ++i) q[i] = a[i];  // q[0]=&a[0][0], q[1]=&a[1][0]...
q + 1;               // ❌ 錯誤:q 是數組類型,不可修改

二維數組綁定實戰

場景 1:函數參數接收二維數組

// ✅ 數組指針:需固定列數
void print_row_ptr(int (*p)[4], int rows) {
    for (int i = 0; i < rows; ++i)
        for (int j = 0; j < 4; ++j)
            printf("%d ", p[i][j]);
}

// ✅ 指針數組:列數可變
void print_ptr_array(int *p[], int rows, int cols) {
    for (int i = 0; i < rows; ++i)
        for (int j = 0; j < cols; ++j)
            printf("%d ", p[i][j]);
}

// ❌ 雙重指針 int** 無法直接接收 int a[3][4]
//    因為 a 退化為 int (*)[4],而非 int**

場景 2:動態分配二維數組

// 方法 A:連續塊 + 數組指針(緩存友好)
int (*p)[4] = malloc(3 * sizeof *p);  // 一次分配 3x4 連續空間

// 方法 B:指針數組 + 分行分配(行長可異)
int **q = malloc(3 * sizeof *q);
for (int i = 0; i < 3; ++i) q[i] = malloc(4 * sizeof *q[i]);

統一訪問語法(四種等價形式)

無論 p 是數組指針還是指針數組,下列四種寫法對 a[i][j] 均有效:

*(p[i] + j)
*(*(p + i) + j)
(*(p + i))[j]
p[i][j]          // 編譯器自動轉換

記憶口訣

「先看右邊」:
int (*p)[4] → 右邊是 [4] → 指向「含 4 個 int 的數組」 → 數組指針
int *p[4] → 右邊是 [4] → 「含 4 個指針的數組」 → 指針數組

常見面試追問

  1. char *p vs char * p:語義無差,但 char *p, a; 中 a 是 char,易誤解;建議 char *p; 貼近變量名。
  2. 二維數組傳給 int**:不可行。需改用 int (*)[N] 或先轉為指針數組。
  3. 返回指針:必須指向堆/靜態/全局記憶體,絕不返回棧地址。

小結

數組指針 = 一個指針,步長 = 整行大小,適合連續二維數組;
指針數組 = 多個指針,各自獨立,適合鋸齒數組、動態行長。
搞清 () 與 [] 結合優先級,配合「先看右邊」口訣,再不會混淆。

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