【22】C语言 - 二维数组详解
文章目录
- [1. 二维数组介绍](#1. 二维数组介绍)
- [2. 二维数组的声明](#2. 二维数组的声明)
- [3. 二维数组的初始化](#3. 二维数组的初始化)
- [4. 访问二维数组的元素](#4. 访问二维数组的元素)
- [5. 使用循环遍历二维数组](#5. 使用循环遍历二维数组)
- [6. 内存中的存储方式](#6. 内存中的存储方式)
- [7. 将二维数组传递给函数](#7. 将二维数组传递给函数)
- [8. 总结与要点](#8. 总结与要点)
1. 二维数组介绍
一个二维数组可以被直观地理解为一个由行 和列组成的表格。
例如,一个2行3列的二维数组可以这样表示:
| 行/列 | 列0 | 列1 | 列2 |
|---|---|---|---|
| 行0 | [0][0] |
[0][1] |
[0][2] |
| 行1 | [1][0] |
[1][1] |
[1][2] |
每个元素通过两个索引(下标)来访问:第一个索引代表行号 ,第二个索引代表列号 。索引总是从0开始。
2. 二维数组的声明
声明一个二维数组需要指定行数 和列数。
语法:
c
数据类型 数组名[行数][列数];
示例:
c
int matrix[3][4]; // 声明一个3行4列(共12个元素)的整型二维数组
float temperatures[5][7]; // 声明一个5行7列的浮点型二维数组
char chessBoard[8][8]; // 声明一个8行8列的字符型二维数组(如棋盘)
3. 二维数组的初始化
方法一:先声明,再初始化
c
#include <stdio.h>
int main(){
//1.先声明再初始化
int arr[3][2];
arr1[0][0] = 1;
arr1[0][1] = 2;
arr1[1][0] = 3;
arr1[1][1] = 4;
arr1[2][0] = 5;
arr1[2][1] = 6;
return 0;
}
方法二:声明的同时,并初始化
c
#include <stdio.h>
int main(){
int matrix[2][3] = {
{1, 2, 3}, // 第0行的元素
{4, 5, 6} // 第1行的元素
};
return 0;
}
方法三:直接列出所有元素(编译器自动计算行数)
一层大括号自动分配。
c
#include <stdio.h>
int main(){
int arr[2][4] = {1,2,3,4,5,6,7,8};
return 0;
}
可以省略行数 ,编译器会根据你提供的数据自动计算行数。但列数绝对不能省略。
c
#include <stdio.h>
int main(){
int arr4[][3] = {1,2,3,4,5,6};
return 0;
}
方法四:部分初始化
未显式初始化的元素会被自动设置为0。
c
#include <stdio.h>
int main(){
// 只初始化第一行,其余行自动为0
int arr1[3][4] = {{1}, {2, 3}};
/* 结果为:
行0: 1, 0, 0, 0
行1: 2, 3, 0, 0
行2: 0, 0, 0, 0
*/
// 将所有元素初始化为0的最简单方法
int arr2[3][4] = {0};
}
4. 访问二维数组的元素
使用数组名后跟两个方括号 [行索引][列索引] 来访问或修改元素。
示例:
c
#include <stdio.h>
int main() {
int table[2][3] = {
{10, 20, 30},
{40, 50, 60}
};
// 访问单个元素
printf("table[0][1] = %d\n", table[0][1]); // 输出:20
printf("table[1][2] = %d\n", table[1][2]); // 输出:60
// 修改元素
table[1][0] = 99;
printf("修改后 table[1][0] = %d\n", table[1][0]); // 输出:99
return 0;
}
5. 使用循环遍历二维数组
遍历二维数组通常需要使用两层嵌套的循环 。
外层循环控制行,内层循环控制列。
示例:打印整个数组
c
#include <stdio.h>
int main() {
int rows = 2, cols = 3;
int table[2][3] = {{1, 2, 3}, {4, 5, 6}};
// 遍历打印
for (int i = 0; i < rows; i++) { // i 循环行
for (int j = 0; j < cols; j++) { // j 循环列
printf("%d ", table[i][j]);
}
printf("\n"); // 打印完一行后换行
}
/* 输出:
1 2 3
4 5 6
*/
return 0;
}
6. 内存中的存储方式
这是理解二维数组的关键:二维数组在内存中是按行优先的顺序连续存储的。
对于数组 int arr[2][3] = {``{1,2,3}, {4,5,6}};,它在内存中的排列顺序是:
行0: 1, 2, 3,
行1: 4, 5, 6
物理地址是连续的:1的地址后面紧跟着2,然后是3,再然后是4,以此类推。
正因为这种连续的线性存储,我们可以用单层循环和指针来遍历它,但更常见的还是用双层循环。
7. 将二维数组传递给函数
将二维数组作为参数传递给函数时,必须指定列的大小 。
这是因为编译器需要知道一行有多少个元素,才能正确计算内存地址。
函数原型示例:
c
// 正确:指定了列数
void printMatrix(int arr[][4], int rows) {
// ...
}
// 也可以明确写出行列,但行数会被忽略,通常用变量传递
void printMatrix(int arr[][4], int rows) {
// ...
}
// 错误:没有指定列数
// void printMatrix(int arr[][], int rows, int cols);
完整示例:
c
#include <stdio.h>
// 函数定义,必须指定列数(这里是4)
void printArray(int arr[][4], int rows) {
for (int i = 0; i < rows; i++) {
for (int j = 0; j < 4; j++) {
printf("%d ", arr[i][j]);
}
printf("\n");
}
}
int main() {
int myArray[3][4] = {
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12}
};
printArray(myArray, 3); // 将数组传递给函数
return 0;
}
8. 总结与要点
| 特性 | 说明 |
|---|---|
| 本质 | 一个"数组的数组",是逻辑上的表格,物理上的连续内存块。 |
| 声明 | type name[rows][cols]; |
| 初始化 | 推荐按行用{}初始化。可以省略行数,但不能省略列数。 |
| 访问 | array[i][j],i为行索引,j为列索引,都从0开始。 |
| 遍历 | 使用两层嵌套循环,外层循环行,内层循环列。 |
| 内存 | 按"行优先"顺序连续存储。 |
| 传参 | 函数参数中必须指定列数(如int arr[][4])。 |