C++二维数组按行优先存储,即arr0→arr0→arr0→arr1→arr1→arr1;这是语言标准规定,使arr[i]可退化为指针且支持i*cols+j索引。

C++ 二维数组在内存中严格按行优先(row-major order)存储,不是按列。
为什么是行优先而不是列优先
这是 C/C++ 语言标准规定的内存布局方式,和 Fortran、MATLAB 等列优先语言完全不同。编译器把 int arr[2][3] 当作一个连续的 6 元素一维块来分配内存,顺序固定为:arr[0][0] → arr[0][1] → arr[0][2] → arr[1][0] → arr[1][1] → arr[1][2]。
这种设计让 arr[i] 能自然退化为指向第 i 行首元素的指针(即 &arr[i][0]),也使得用一维索引 arr[i * cols + j] 访问元素时逻辑一致。
常见误判场景:指针类型混淆
错误地认为 int (*p)[3] = arr; 和 int *p = &arr[0][0]; 是等价的——它们指向同一地址,但类型语义完全不同:
立即学习“C++免费学习笔记(深入)”;
-
int (*p)[3]是“指向含 3 个的数组”的指针,<code>p + 1跳过一整行(12 字节) -
int *p是普通int指针,p + 1只跳过一个int(4 字节)
若混用,比如用 *(p + 1) 去读 arr[1][0](期望跳过整行),实际只跳了 1 个元素,就会越界或读错值。
验证方法:用地址差直接看布局
写一段小代码打印相邻元素地址:
int arr[2][3] = {{1,2,3}, {4,5,6}};
printf("arr[0][0]: %p\n", (void*)&arr[0][0]);
printf("arr[0][1]: %p\n", (void*)&arr[0][1]);
printf("arr[1][0]: %p\n", (void*)&arr[1][0]);
输出会显示:arr[0][1] 地址比 arr[0][0] 大 sizeof(int),而 arr[1][0] 比 arr[0][2] 大 sizeof(int),直接证明是“填满一行再下一行”。
行优先是底层事实,不是可选项;所有基于指针算术、memcpy 批量拷贝、或与 C 风格 API(如 OpenGL、CBLAS)交互时,都必须按这个顺序组织数据,否则轻则结果错乱,重则段错误。


















