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

C 語言動態二維陣列實作指南:單一記憶體區塊與指標陣列法

     編輯:關於C語言

前言:為何需要動態二維陣列?

C 語言原生不支援真正的二維陣列,所謂「二維陣列」實為「陣列的陣列」。靜態宣告 int a[10][20] 編譯期即固定大小,若需依執行期輸入決定維度,必須動態配置記憶體。本文介紹高效、通用的單一記憶體區塊配置法,避免傳統指標陣列逐列 malloc 造成的記憶體碎片與釋放麻煩。

核心原理:指標運算與記憶體佈局

對 p[i][j],編譯器轉換為 *(*(p+i)+j):

  1. p+i:計算第 i 列指標
  2. *(p+i):取得該列首元素位址(指標)
  3. *(p+i)+j:計算第 j 個元素位址
  4. *(*(p+i)+j):取值

因此,我們只需配置一個指標陣列(列指標),再配置一塊連續記憶體存放所有元素,將列指標指向對應位移即可。

完整實作程式碼

型別定義與錯誤代碼

typedef unsigned char MK_Byte;
#define SUCCESS 0
#define MFAILED 1
#define MNOMEMORY 2

// 宣告巨集:確保初始化為 NULL
#define DeclareTwoDArray(ATYPE, iname) ATYPE ** iname = NULL

// 記憶體操作巨集:便於移植與除錯
#define MKMALLOC(nsize) malloc(nsize)
#define MKFREE(name) \
    if (NULL != name) { \
        free(name); \
        name = NULL; \
    }

建立動態二維陣列

int MKCreatArray(int nsize, int X, int Y, void ***parray) {
    void **tdarray = NULL;      // 列指標陣列
    MK_Byte *tmparray = NULL;   // 實際資料區塊
    int i = 0;

    *parray = NULL;

    // 1. 配置列指標陣列 (Y 個指標)
    if (!(tdarray = (void **)MKMALLOC(sizeof(MK_Byte *) * Y)))
        return MNOMEMORY;

    // 2. 配置連續資料區塊 (X*Y 個元素)
    if (!(tmparray = (MK_Byte *)MKMALLOC(nsize * X * Y))) {
        MKFREE(tdarray);
        return MNOMEMORY;
    }

    // 3. 歸零初始化
    memset(tmparray, 0x00, nsize * X * Y);

    // 4. 設定列指標指向正確位移
    for (i = 0; i < Y; i++)
        tdarray[i] = tmparray + (i * X) * nsize;

    *parray = tdarray;
    return SUCCESS;
}

釋放動態二維陣列

void MKFreeArray(void ***parray) {
    if (*parray) {
        MKFREE((*parray)[0]); // 釋放資料區塊
        MKFREE(*parray);      // 釋放指標陣列
    }
}

使用範例

void testTwoDArray() {
    DeclareTwoDArray(int, a);
    DeclareTwoDArray(float, b);

    // 建立 3行 x 2列 int 陣列
    MKCreatArray(sizeof(int), 3, 2, &a);
    a[1][2] = 10;  // 注意:索引 0-based,此處為第 2 行第 3 列
    a[0][1] = 23;
    printf("%d,%d\n", a[1][2], a[0][1]);
    MKFreeArray(&a);

    // 重新配置 6x6
    MKCreatArray(sizeof(int), 6, 6, &a);
    a[5][5] = 234;
    a[4][0] = 567;
    printf("%d,%d\n", a[5][5], a[4][0]);
    MKFreeArray(&a);

    // 建立 float 陣列
    MKCreatArray(sizeof(float), 2, 2, &b);
    b[0][0] = 0.5f;
    b[1][1] = 0.006f;
    printf("%g,%g\n", b[0][0], b[1][1]);
    MKFreeArray(&b);
}

優勢分析

特性傳統逐列 malloc本文單一區塊法
記憶體碎片多,易造成外部碎片無,單一連續區塊
快取效能差,資料分散優,空間局部性佳
釋放複雜度需迴圈逐列 free兩次 free 完成
型別通用性需為每型別寫函數void** 通用,支援任意型別
錯誤處理部分配置失敗難回滾失敗自動釋放已配置區塊

注意事項

  • 參數順序:MKCreatArray(sizeof(type), 欄數X, 列數Y, &ptr),X 對應第二維度(行),Y 對應第一維度(列)
  • 索引範圍:a[0..Y-1][0..X-1],切勿越界
  • 記憶體對齊:若型別需對齊(如 double),建議配置時對齊至 8 位元組邊界
  • 嵌入式系統:若無 malloc,可改用靜態記憶體池實作相同介面

總結

單一記憶體區塊配合指標陣列,是 C 語言實作動態二維陣列的最佳實踐:效能高、釋放簡單、型別通用。提供的 MKCreatArray/MKFreeArray 組合可直接納入專案,解決動態矩陣配置痛點。

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