C语言二维数组按行优先连续存储,取第j列需固定j、遍历i访问arri;&arr0不能作列指针,因同列元素内存不连续;越界访问将导致未定义行为。

用 for 循环遍历行索引取列
二维数组在内存中是按行优先连续存储的,没有“列指针”这种东西。要取第 j 列所有元素,本质是固定列下标 j,让行下标 i 从 0 走到 rows-1。
- 假设数组定义为
int arr[ROWS][COLS],取第2列(即索引2)就是循环访问arr[0][2]、arr[1][2]、…、arr[ROWS-1][2] - 注意:C++ 不检查数组越界,
j超出[0, COLS)或i超出[0, ROWS)会读到垃圾值或触发未定义行为 - 如果用
std::vector<:vector>></:vector>,同样要确保每个内层vector长度 ≥ 所需列号,否则v[i][j]可能越界
用 std::transform + lambda 提取列(适合 vector)
如果你用的是 std::vector<:vector>></:vector>,且想把某一列转成新容器(比如 std::vector<t></t>),std::transform 比裸循环更清晰:
std::vector<std::vector<int>> mat = {{1,2,3}, {4,5,6}, {7,8,9}};
int col_idx = 1;
std::vector<int> col;
col.reserve(mat.size()); // 避免多次 realloc
std::transform(mat.begin(), mat.end(), std::back_inserter(col),
[col_idx](const auto& row) { return row.at(col_idx); });
// col 现在是 {2, 5, 8}
- 用
row.at(col_idx)而非row[col_idx],能在运行时捕获列越界异常 -
reserve()是可选但推荐的,避免插入过程中的重复内存分配 - 如果某一行长度不够,
at()抛std::out_of_range;用[]就直接 UB
为什么不能用 &arr[0][j] 当“列数组”首地址?
有人想取列的“连续内存块”,比如写 int* col_ptr = &arr[0][j],再当一维数组用——这不行。
-
&arr[0][j]指向的是第0行第j列,下一个同列元素在内存中距离它sizeof(int) * COLS字节,不是sizeof(int) - 也就是说,
col_ptr[1]实际读的是arr[0][j+1](同一行下一列),而不是你想要的arr[1][j] - 这种误用在调试器里看值会完全错乱,且无编译错误
动态二维数组(new int*[rows])取列要额外小心
如果用指针数组模拟二维数组:int** arr = new int*[rows]; for(...) arr[i] = new int[cols];,取列逻辑不变,但风险更高:
立即学习“C++免费学习笔记(深入)”;
- 每一行内存不连续,
arr[i]是独立分配的,arr[i][j]访问依赖两次解引用 - 必须确保所有
arr[i]都已分配且长度 ≥j+1,否则arr[i][j]是野指针访问 - 释放时得双重循环
delete[] arr[i]再delete[] arr,漏掉任何一层都会内存泄漏
除非有明确性能/接口约束,否则优先用 std::vector<:vector>></:vector> 或一维数组模拟(arr[i * cols + j]),后者取列虽需计算索引,但内存连续、缓存友好。


















