C++二维数组必须指定列数,因编译器需列数计算内存偏移;行数可省略由初始化器推导;传参时列数不可省,本质是“指向含N个int的数组”的指针;sizeof求维数仅适用于未退化的栈上数组。

int arr[行数][列数] 是 C++ 二维数组最基础、最直接的写法,编译器要求行数和列数都必须是常量表达式(比如字面量、constexpr 变量),不能是运行时变量。
为什么必须写明列数?
因为编译器靠列数计算内存偏移:arr[i][j] 实际被展开为 *(&arr[0][0] + i * 列数 + j)。如果列数不固定,编译器无法确定每行占多少字节,也就没法算出 arr[1][0] 在哪——这会导致编译错误,不是警告。
四种常见初始化写法及差异
以下写法都合法,但语义和可读性不同:
-
int arr[2][3] = {{1,2,3}, {4,5,6}};—— 推荐。结构清晰,明确每行内容,修改某行数据时不易错位 -
int arr[2][3] = {1,2,3,4,5,6};—— 编译器按行优先填充,但易误读(比如以为是列优先),调试时难定位逻辑 -
int arr[2][3] = {{1}, {4}};—— 部分初始化,未显式赋值的元素自动为 0(仅对static或全局数组保证;局部数组也通常如此,但依赖编译器实现) -
int arr[][3] = {1,2,3,4,5,6};—— 行数由初始化器推导为 2,列数仍强制指定;适合数据量固定但行数可能变化的场景(如配置表)
传参时列数不能省略
函数参数里写 void func(int a[2][3]) 或 void func(int a[][3]) 都可以,但 [3] 不可省。写成 void func(int a[][]) 直接报错。更本质的写法是 void func(int (*a)[3]),强调 a 是“指向含 3 个 int 的数组”的指针——这才是二维数组退化的真正类型。
立即学习“C++免费学习笔记(深入)”;
sizeof 求行列数的可靠方式
对栈上定义的静态二维数组(如 int arr[2][3]),可用:
- 行数:
sizeof(arr) / sizeof(arr[0]) - 列数:
sizeof(arr[0]) / sizeof(arr[0][0])
这个技巧只在数组未退化为指针时有效。一旦传进函数,sizeof(a) 就变成指针大小(通常是 8),结果完全不可信。
实际写代码时,最容易忽略的是:把局部二维数组传给函数后,还试图用 sizeof 算行列数——那得到的不是维度,是地址长度。


















