一、二维数组的基本概念
-
定义:二维数组是数组的数组,可以看作是由行和列组成的表格
-
特点:
-
所有元素具有相同的数据类型
-
在内存中按行优先顺序连续存储
-
通过两个下标(行索引和列索引)访问元素,都从0开始
-
强调:定义数组时必须指定数据类型,不允许auto关键字(C新特性)由初始值的列表推新类型。
二、二维数组的声明和初始化
1. 数组声明
数据类型 数组名[行数][列数];
示例:
int matrix[3][4]; // 3行4列的整型二维数组
float grid[5][5]; // 5行5列的浮点型二维数组
char board[8][8]; // 8行8列的字符型二维数组
2. 数组初始化
(1) 完全初始化(按行):
int matrix[2][3] = {
{1, 2, 3},
{4, 5, 6}
};
(2) 线性初始化(编译器自动填充):
int matrix[2][3] = {1, 2, 3, 4, 5, 6};
(3) 部分初始化(未初始化的元素自动设为0):
int matrix[3][4] = {
{1},
{2, 3},
{4, 5, 6}
};
(4) 不指定行数初始化(编译器自动计算行数):
int matrix[][3] = {
{1, 2, 3},
{4, 5, 6},
{7, 8, 9}
}; // 自动确定为3行
(5) C99新增的指定初始化方式:
int matrix[3][3] = {
[0][0] = 1, [1][1] = 5, [2][2] = 9
};
强调:一些编译器支持数组赋值,即编译器扩展,但是好避免使用非标准特性,应为可能导致在其它原编译器无法工作。
三、二维数组元素的访问
-
通过行列下标访问:
int matrix[2][3] = {{1, 2, 3}, {4, 5, 6}}; int x = matrix[0][1]; // 访问第1行第2列元素,x=2 matrix[1][2] = 10; // 修改第2行第3列元素为10
-
2.下标范围:
-
行下标:0到(行数-1)
-
列下标:0到(列数-1)
-
越界访问是未定义行为
-
四、二维数组在内存中的存储
-
行优先存储:C语言中二维数组按行顺序连续存储
-
例如
int a[2][3]
在内存中的顺序是:a[0][0], a[0][1], a[0][2], a[1][0], a[1][1], a[1][2]
-
-
计算数组大小:
int matrix[3][4]; size_t total_size = sizeof(matrix); // 整个数组的字节大小 size_t row_size = sizeof(matrix[0]); // 一行的字节大小 size_t element_size = sizeof(matrix[0][0]); // 单个元素的字节大小 int rows = sizeof(matrix) / sizeof(matrix[0]); // 行数 int cols = sizeof(matrix[0]) / sizeof(matrix[0][0]); // 列数
五、二维数组与指针的关系
-
二维数组名是指向第一行的指针
-
二维数组可以看作是一维数组的数组
-
指针表示法:
int matrix[3][4]; int (*ptr)[4] = matrix; // 指向包含4个int的数组的指针
-
使用指针访问元素:
printf("%d", *(*(matrix + 1) + 2)); // 等价于matrix[1][2]
六、二维数组作为函数参数
-
传递方式:
// 方式1:明确指定列数 void func(int arr[][4], int rows); // 方式2:使用指针形式 void func(int (*arr)[4], int rows);
-
调用示例:
int matrix[3][4] = {...}; func(matrix, 3);
-
重要限制:必须指定列数(除第一维外其他维必须指定)
七、常见二维数组操作
1. 遍历二维数组
int matrix[3][4] = {...};
for(int i = 0; i < 3; i++) {
for(int j = 0; j < 4; j++) {
printf("%d ", matrix[i][j]);
}
printf("\n");
}
2. 矩阵转置
void transpose(int src[][3], int dest[][3], int size) {
for(int i = 0; i < size; i++) {
for(int j = 0; j < size; j++) {
dest[j][i] = src[i][j];
}
}
}
3. 矩阵乘法
void matrixMultiply(int a[][N], int b[][M], int result[][M], int rows) {
for(int i = 0; i < rows; i++) {
for(int j = 0; j < M; j++) {
result[i][j] = 0;
for(int k = 0; k < N; k++) {
result[i][j] += a[i][k] * b[k][j];
}
}
}
}
4. 查找最大元素及其位置
void findMax(int arr[][4], int rows, int *max, int *row, int *col) {
*max = arr[0][0];
*row = 0;
*col = 0;
for(int i = 0; i < rows; i++) {
for(int j = 0; j < 4; j++) {
if(arr[i][j] > *max) {
*max = arr[i][j];
*row = i;
*col = j;
}
}
}
}
八、多维数组的概念
-
C语言支持更高维度的数组(三维、四维等)
-
声明方式:
int cube[3][3][3]; // 三维数组
九、注意
-
内存布局:理解行优先存储方式对性能优化很重要
-
参数传递:函数参数中必须指定除第一维外的所有维度
-
指针类型:指向二维数组的指针类型与指向一维数组的指针不同
-
数组与指针:
-
matrix
的类型是"指向包含4个int的数组的指针" -
matrix[0]
的类型是"指向int的指针"
-
-
越界访问:C语言不检查多维数组的下标越界