问题的背景
C语言中的多维数组最初被设计用于简化与表格和矩阵的操作。经典的二维数组是数组的数组,可以使用简单的语法来处理表格数据的元素。随着时间的推移,尤其是在处理可变长度数组时,这种方法得到了发展。
问题
不正确的声明和初始化多维数组会导致编译错误或逻辑故障。在将多维数组传递到函数时,许多开发者会因为规范的要求而感到困惑——必须明确指定除第一个维度之外的所有维度的大小。
解决方案
声明二维数组:
int matrix[3][4];
完全初始化:
int matrix[2][3] = { {1, 2, 3}, {4, 5, 6} };
传递到函数时——必须明确指定除第一个以外的所有尺寸:
void printMatrix(int m[][3], int rows) { for (int i = 0; i < rows; ++i) { for (int j = 0; j < 3; ++j) printf("%d ", m[i][j]); printf(" "); } }
随着C99标准的引入,可以声明接受可变长度数组的函数:
void foo(int rows, int cols, int a[rows][cols]);
关键特性:
1. 可以声明一个不指定第二个大小的二维数组的函数吗?
不可以,C要求在编译时所有尺寸,除了第一个,必须是已知的。这与访问元素时的指针算术有关。
错误示例:
// 错误: void process(int arr[][], int rows); // 不可以
2. 如果不初始化所有的多维数组元素会发生什么?
如果数组是静态或全局的,剩余的元素将自动填充为零。对于局部数组的部分初始化,隐式初始化的元素也将为零。
int a[2][3] = {{1}, {4}}; // a[0][1] 和 a[0][2],a[1][1] 和 a[1][2] 将变为 0
3. 指针数组和二维数组之间有什么区别?
二维数组是一个连续的内存块。指针数组是指向单独的一维数组的指针的集合,这在为“破碎的”数组分配内存时很重要。
尝试声明并在函数中传递一个没有指定第二个大小的二维数组,这将导致编译错误。表面的修复通过替换为指针导致进一步计算时的未定义或不正确行为。
优点:
缺点:
开发者明确指定所有维度的大小,在文档中解释元素在内存中的存储顺序,从而减少后续维护中的错误数量。
优点:
缺点: