👇😊 C语言二维数组深度解析! 😊👇


🌈 1. 二维数组是什么?

现在你的手里一个数学表格📊,或者一个棋盘♟️,每个格子可以存放一个数据。

  • 行(Row) → 横向排列(比如Excel中的行号)
  • 列(Column) → 纵向排列(比如Excel中的列标)
  • 元素 → 每个格子里的数据

例如

1
2
3
4
5
6
7
8
9
学生成绩表(3个学生,2门课)
行 → 学生 | 列 → 科目
+----+----+
| 80 | 90 | → 学生1的成绩
+----+----+
| 70 | 85 | → 学生2的成绩
+----+----+
| 95 | 88 | → 学生3的成绩
+----+----+

🌈 2. 二维数组的声明与初始化

2.1 声明二维数组

📝 语法数据类型 数组名[行数][列数];

1
int scores[3][2];  // 3行2列的整型数组(3学生×2科目)

2.2 初始化二维数组

  • 逐行初始化:用大括号分组

    1
    2
    3
    4
    5
    int scores[3][2] = {
    {80, 90}, // 第0行:学生1的语文和数学成绩
    {70, 85}, // 第1行:学生2的成绩
    {95, 88} // 第2行:学生3的成绩
    };
  • 省略行数(编译器自动计算行数):

    1
    2
    3
    4
    5
    int scores[][2] = { 
    {80, 90},
    {70, 85},
    {95, 88}
    };
  • 不完整初始化:剩余元素补0

    1
    2
    3
    4
    int matrix[2][3] = {
    {1}, // 第0行 → [1,0,0]
    {2,3} // 第1行 → [2,3,0]
    };

🌈 3. 访问二维数组元素

  • 索引规则数组名[行号][列号]
  • 索引从0开始!最大行号 = 行数-1,最大列号 = 列数-1

🌰 例子

1
2
3
4
int scores[3][2] = {{80,90}, {70,85}, {95,88}};

printf("%d", scores[0][1]); // 输出第0行第1列 → 90
scores[2][0] = 100; // 修改第2行第0列 → 变成100

💥 致命错误:越界访问!

1
2
scores[3][0] = 60; // ❌ 行号最大是2(共3行)
scores[1][2] = 75; // ❌ 列号最大是1(共2列)

🌈 4. 内存中的二维数组

二维数组在内存中是按行连续存储的!
例如 int arr[2][3] = {{1,2,3}, {4,5,6}} 的内存布局:

1
2
地址低 → 高
1 2 3 4 5 6
  • 访问 arr[1][1] → 实际是第 1*3 +1 =4 个元素(值5)

用一维视角理解二维数组

可以把二维数组看作一个“被折叠”的一维数组:

1
2
3
int arr[2][3] = {{1,2,3}, {4,5,6}};
// 等价于
int arr_flat[6] = {1,2,3,4,5,6};

🌈 5. 遍历二维数组

嵌套循环:外层循环行,内层循环列

1
2
3
4
5
6
7
8
int scores[3][2] = {{80,90}, {70,85}, {95,88}};

for(int i=0; i<3; i++) { // 遍历行
for(int j=0; j<2; j++) { // 遍历列
printf("%d ", scores[i][j]);
}
printf("\n"); // 换行
}

输出:

1
2
3
80 90 
70 85
95 88

🌈 6. 二维数组与指针

二维数组名是指向第一个元素(即第0行)的指针

1
2
3
4
5
int arr[2][3] = {{1,2,3}, {4,5,6}};
int (*p)[3] = arr; // p指向第0行(整个一维数组)

// 访问第1行第2列 → 6
printf("%d", p[1][2]); // 等价于 arr[1][2]

🌈 7. 动态二维数组(进阶)

使用指针数组 + malloc 动态创建二维数组:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
int rows = 3, cols = 2;
int **matrix = (int **)malloc(rows * sizeof(int *)); // 申请行指针
for(int i=0; i<rows; i++) {
matrix[i] = (int *)malloc(cols * sizeof(int)); // 每行申请列空间
}

// 赋值
matrix[0][0] = 1;

// 释放内存(先释放列,再释放行)
for(int i=0; i<rows; i++) {
free(matrix[i]);
}
free(matrix);

🌈 8. 常见错误

  1. 行列顺序颠倒

    1
    2
    int arr[2][3];
    arr[3][2] = 5; // ❌ 行号最大1,列号最大2
  2. 错误初始化

    1
    2
    3
    int arr[2][3] = {1,2,3,4,5,6}; // ✅ 但可读性差
    int arr[2][3] = {{1,2}, {3}}; // ✅ 补0 → [1,2,0], [3,0,0]
    int arr[2][3] = {{1,2,3,4}}; // ❌ 第0行元素过多
  3. 动态数组未释放内存 → 内存泄漏!


🌈 9. 练习时间!

练习1:求二维数组的总和

写一个函数 int sumMatrix(int matrix[][3], int rows),计算3列二维数组所有元素的和。

练习2:矩阵转置

写一个函数 void transpose(int src[][3], int dest[][2], int rows),将2行3列的矩阵转置为3行2列的矩阵(行列互换)。

练习3:动态创建二维数组

动态创建一个4行5列的整型二维数组,并初始化所有元素为0。


🎯 参考答案

练习1

1
2
3
4
5
6
7
8
9
int sumMatrix(int matrix[][3], int rows) {
int sum = 0;
for(int i=0; i<rows; i++) {
for(int j=0; j<3; j++) {
sum += matrix[i][j];
}
}
return sum;
}

练习2

1
2
3
4
5
6
7
void transpose(int src[][3], int dest[][2], int rows) {
for(int i=0; i<rows; i++) {
for(int j=0; j<3; j++) {
dest[j][i] = src[i][j]; // 行列互换
}
}
}

练习3

1
2
3
4
5
6
7
8
int rows = 4, cols = 5;
int **matrix = (int **)malloc(rows * sizeof(int *));
for(int i=0; i<rows; i++) {
matrix[i] = (int *)malloc(cols * sizeof(int));
for(int j=0; j<cols; j++) {
matrix[i][j] = 0; // 初始化
}
}

🚀 总结:二维数组就是“数组的数组”,想象成表格或棋盘更容易理解!掌握行优先存储、嵌套循环遍历和动态内存管理,其实二维数组也不难!