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

C語言二維數組與指針進階:從語法糖到底層內存佈局的完整圖解

     編輯:關於C語言

一維數組:指針與下標的等價性

int a[10];
a[i]    // 由編譯器轉換為 *(a + i)
*(a+i)  // 指針算術:地址 + i * sizeof(int)
i[a]    // 合法但極不推薦(加法交換律)

本質:數組名在表達式中(除 sizeof、& 外)退化為指向首元素的指針。

二維數組:數組的數組

int calendar[12][31];  // 12 個「含 31 個 int 的數組」組成的數組
  • calendar:指向首個「31-int 數組」的指針,類型 int (*)[31]。
  • calendar[4]:第 5 個子數組,類型 int [31],退化為 int * 指向其首元素。
  • calendar[4][7] ≡ *(calendar[4] + 7) ≡ *(*(calendar + 4) + 7)。

指針遍歷二維數組的正確姿勢

int (*monthp)[31] = calendar;  // 指向「31-int 數組」的指針
for (monthp = calendar; monthp < &calendar[12]; monthp++) {
    int *dayp = *monthp;       // *monthp 退化為 int*,指向該行首元素
    for (dayp = *monthp; dayp < &(*monthp)[31]; dayp++) {
        *dayp = 0;
    }
}

關鍵點:

  1. monthp++ 步進 sizeof(int[31]) (124 字節),完美跨行。
  2. &calendar[12] 是「第 13 行」地址(不存在),作為終止哨兵,合法參與比較。
  3. &(*monthp)[31] 同理為行尾哨兵。

常見錯誤:int **p = calendar; 為何非法?

  • calendar 類型 int (*)[31](指向數組的指針)。
  • int **p 類型 int **(指向指針的指針)。
  • 兩者指向類型不同,編譯器報錯。即使強轉,解引用時步長也會錯(4 字節 vs 124 字節)。

字符串數組特例:char *strs[] ≡ char **strs

因為字符串處理只關心 char * 層面,printf("%s", strs[i]) 只需一級解引用,二級指針與數組退化指針在這種用法下行為一致。

總結:下標 vs 指針

場景推薦理由
一般業務代碼下標 a[i][j]可讀性強,編譯器優化同等
高性能掃描/拷貝指針 *p++減少索引計算,利用自增寻址模式
動態分配二維數組指針數組 int **p + 每行 malloc行長可變,非連續內存
靜態大小、需連續內存真二維數組 int a[M][N]單塊內存,緩存友好,指針步進正確
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved