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

C語法陷阱:二維數組模擬與指針運算深度解析

     編輯:關於C

C 語言二維數組本質是「數組的數組」,指針運算極易出錯。本文從 *a 引用語義出發,層層推導二維數組指針表達式、參數傳遞、指向數組的指針聲明,並展示遍歷陷阱與編譯器兼容性問題。

基礎:一維數組指針等價性


*a        ≡ a[0]       // 首元素引用
*(a+i)    ≡ a[i]       // 第 i 元素引用
a+i       ≡ &a[i]      // 第 i 元素地址

甚至 i[a] 合法(因 a+i ≡ i+a),但**強烈不推薦**。

二維數組聲明與含義


int calendar[12][31];  // 12 個元素的數組,每元素是 31 個 int 的數組

calendar[4] 是什麼?

  • 第 5 個元素(下標 4)
  • 類型:int[31](含 31 個 int 的數組)
  • sizeof(calendar[4]) == 31 * sizeof(int)
  • 可隱式轉換為 int* 指向首元素

多維下標等價轉換


calendar[4][7]
≡ *(calendar[4] + 7)
≡ *(*(calendar + 4) + 7)

指針聲明陷阱


int *p;
p = calendar;      // ❌ 錯誤:類型不匹配
                   // calendar 是 int(*)[31](指向數組的指針)
                   // p 是 int*(指向 int 的指針)

正確聲明:指向數組的指針


int (*ap)[31];     // ap 是指向 int[31] 的指針
int (*monthp)[31] = calendar;  // ✅ 合法

讀法:*ap 是數組 → ap 是指向數組的指針。

遍歷二維數組:下標法 vs 指針法

下標法(推薦)


for(month=0; month<12; month++)
    for(day=0; day<31; day++)
        calendar[month][day] = 0;

指針法(教學用)


int (*monthp)[31];
for(monthp = calendar; monthp < &calendar[12]; monthp++) {
    int *dayp;
    for(dayp = *monthp; dayp < &(*monthp)[31]; dayp++)
        *dayp = 0;
}

⚠️ 早期編譯器可能不支援 &(*monthp)[31] 寫法,現代 GCC/Clang/MSVC 均可編譯。

函數參數傳遞差異

聲明實際類型適用場景
void f(int a[12][31])int (*a)[31]列數固定
void f(int a[][31])int (*a)[31]列數固定,行數不固定
void f(int *a[12])int **a指針陣列(鋸齒)
void f(int **a)int **a指針陣列

核心區別總結

// 二維數組:連續塊
int a[3][4];  // sizeof=48, a+1 增加 16 bytes

// 指向數組的指針
int (*p)[4] = a;  // p+1 增加 16 bytes

// 指針陣列:分散塊
int *q[3];  // q+1 增加 8 bytes (64位)

避坑指南

  • ✅ 二維數組參數**必須指定列數**
  • ✅ 用 int (*p)[N] 指向二維數組
  • ✅ 遍歷優先用下標法,可讀性高、編譯器優化好
  • ✅ 動態分配二維數組:malloc(rows * cols * sizeof(int)) + 手動索引
  • ❌ 不要用 int ** 接收二維數組
  • ❌ 不要混淆「指向數組的指針」與「指針陣列」

動態分配二維數組最佳實踐


// 方法 1:單塊連續(推薦,緩存友好)
int *flat = malloc(rows * cols * sizeof(int));
#define IDX(r,c) flat[(r)*cols + (c)]

// 方法 2:指針陣列(行長度可變)
int **rows = malloc(rows * sizeof(int*));
for(i=0; i
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved