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

C 語言二維陣列完整指南:記憶體佈局、位址計算與矩陣運算實戰

     編輯:關於C語言

二維陣列是矩陣運算、影像處理、棋盤遊戲的基礎資料結構。本文完整解析 C 語言二維陣列的Row-major 記憶體佈局、指標等價關係、動態配置三種模式、函式參數傳遞,並以「分科成績統計」實戰範例串聯核心觀念。

宣告與靜態初始化


int matrix[3][4] = {
    {0, 1, 2, 3},
    {4, 5, 6, 7},
    {8, 9, 10, 11}
};
// 等價於 int matrix[3][4] = {0,1,2,3,4,5,6,7,8,9,10,11};(按列序)
  • 第一維(列數)可省略:int m[][4] = {...};
  • 第二維(行數)不可省略,編譯器需知列寬計算位移。

記憶體佈局:Row-major 連續儲存

邏輯上 3×4 矩陣,物理上為 12 個 int 連續排列:

位址: 1000 1004 1008 1012 | 1016 1020 1024 1028 | 1032 1036 1040 1044
值:     0    1    2    3  |   4    5    6    7  |   8    9   10   11
       ←──── 列 0 ────→    ←──── 列 1 ────→    ←──── 列 2 ────→

a[i][j] 位址公式:base + (i * COLS + j) * sizeof(int)

指標等價關係完整表

表示式型別值/含義
aint (*)[4]陣列位址 = 第 0 列位址
a[0], *a, &a[0][0]int*第 0 列首元素位址
a+1, &a[1]int (*)[4]第 1 列位址(+16 bytes)
a[i], *(a+i), &a[i][0]int*第 i 列首元素位址
a[i]+j, *(a+i)+j, &a[i][j]int*第 i 列第 j 元素位址
*(*(a+i)+j), a[i][j]int元素值

三種動態配置模式比較

模式程式碼記憶體特性適用場景
單一連續區塊int *p = malloc(r*c*sizeof(int));完全連續,p[i*c+j] 存取高效能、需傳給 qsort/BLAS
指標陣列(列指標)int **p = malloc(r*sizeof(int*)); for(i) p[i]=malloc(c*sizeof(int));各列獨立,不連續列長度不一、頻繁增刪列
指向陣列的指標int (*p)[C] = malloc(r*sizeof(int[C]));完全連續,保留 p[i][j] 語法編譯期知行數 C、需二維語法

模式一:單一連續區塊(推薦高效能)


int *mat = malloc(rows * cols * sizeof(int));
mat[i*cols + j] = val;  // 手動計算索引
// 釋放:free(mat);

模式三:保留二維語法(C99 VLA 或固定行數)


// 固定行數 COLS
int (*mat)[COLS] = malloc(rows * sizeof(int[COLS]));
mat[i][j] = val;  // 自然語法
// 釋放:free(mat);

實戰範例:分科成績統計


#include 
#define STUDENTS 5
#define SUBJECTS 3

int main() {
    int score[STUDENTS][SUBJECTS];
    float avg[SUBJECTS] = {0};
    int i, j;

    printf("輸入 %d 位學生 %d 科成績:\n", STUDENTS, SUBJECTS);
    for (j = 0; j < SUBJECTS; ++j) {
        for (i = 0; i < STUDENTS; ++i) {
            scanf("%d", &score[i][j]);
            avg[j] += score[i][j];
        }
        avg[j] /= STUDENTS;
    }

    printf("\n科目平均: ");
    for (j = 0; j < SUBJECTS; ++j) printf("%.1f ", avg[j]);
    float total = 0;
    for (j = 0; j < SUBJECTS; ++j) total += avg[j];
    printf("\n全科總平均: %.1f\n", total / SUBJECTS);
    return 0;
}

函式參數傳遞:二維陣列退化規則


// 正確:指定行數
void print(int a[][4], int rows);
void print(int (*a)[4], int rows);  // 等價

// 錯誤:int a[][]、int **a(除非動態配置模式二)

呼叫時直接傳陣列名:print(mat, 3); → mat 退化為 int(*)[4]。

進階:矩陣轉置與乘法

就地轉置(方陣)


void transpose(int n, int a[][n]) {  // C99 VLA
    for (int i=0; i

矩陣乘法 C = A × B


void matmul(int r1, int c1, int c2,
            int A[][c1], int B[][c2], int C[][c2]) {
    for (int i=0; i

常見錯誤總結

  1. int a[][] 參數宣告 → 編譯錯誤(行數未知)。
  2. int **p = a; 型別不匹配(靜態二維陣列非指標陣列)。
  3. 動態配置模式二忘記逐列 free → 記憶體洩漏。
  4. VLA 用於大型矩陣 → 棧溢位(改用 malloc)。
  5. 矩陣乘法迴圈順序 i-k-j 可提升快取命中率(c1 較大時)。

掌握 Row-major 佈局與三種動態配置模式,二維陣列操作將不再有隱藏驚悚。

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