如何在C/C++中获取多维数组的列?

问题描述 投票:0回答:10
int matrix[9][9],*p;
p=matrix[0]; 

这有效并给出了第一行

matrix
,但是如何获得
matrix
的第一列我已经尝试过
p=matrix[][0];
?我也不明白为什么下面的代码会出现编译器错误?

int matrix[9][9],p[9];  // it looks really ugly, byt why it doesn't work ?
p=matrix[0];            // compiler gives "invalid array assigment"

是因为多维数组是数组的数组 - 我们应该将

matrix[i][j]
解释为第 i 个嵌套数组的第 j 个元素吗?

c++ c arrays multidimensional-array variable-assignment
10个回答
16
投票

在C/C++中,多维数组实际上存储为一维数组(在内存中)。您的二维矩阵存储为具有行优先排序的一维数组。这就是为什么从中获取列并不容易,并且默认情况下不提供。 内存中不存在可以获取代表多维数组列的指针的连续数组。见下文:

当您执行

p=matrix[0]
时,您只是获得了指向第一个元素的指针
matrix[0][0]
,这让您认为您获得了指向第一行的指针。实际上,它是一个指向保存
matrix
的整个连续数组的指针,如下:

matrix[0][0]
matrix[0][1]
matrix[0][2]
.
.
matrix[1][0]
matrix[1][1]
matrix[1][2]
.
.
matrix[8][0]
matrix[8][1]
matrix[8][2]
.
.
matrix[8][8]

如上所示,任何给定列的元素都被相应行中的其他元素分隔开。

因此,作为旁注,如果您愿意,可以使用指针

p
遍历矩阵的全部 81 个元素。


8
投票

您可以使用类似的循环来获取第一列

for(int i = 0; i < 9; i++)
{
    printf("Element %d: %d", i, matrix[i][0]);
}

我认为分配不能正常工作,因为你试图分配一些不是指针地址的东西。

(抱歉这是c代码)


4
投票

指定

matrix[81]
matrix[9][9]

之间没有区别

matrix[r][c]
matrix[9*r+c]

的意思相同

还有其他更适合多维数组的容器,例如

boost::multi_array

http://www.boost.org/doc/libs/1_53_0/libs/multi_array/doc/index.html

将裸数组想象成分配一块连续的内存。那么你,程序员就必须自己处理这块内存。数组的裸名称,例如

matrix
是指向该分配的内存块的第一个元素的指针。那么
*(matrix+1)
matrix[0][1]
matrix[1]
相同。


2
投票

p 是一个 int 数组,matrix[0] 是一个指针..


1
投票

matrix
本身是最接近数组列的东西,因为
(matrix + 1)[0][0]
matrix[1][0]
相同。


1
投票

这是一个构建 10x10 数组并打印第二列的程序:

#include <iostream>

using namespace std;

int main()
{
   int aa[10][10];

   for(int i = 0; i<10; i++)
       for(int j = 0; j<10; j++)
           aa[i][j] = i*10+j;
   
   int col = 2;

   // pointer to a length-10 1d array
   int (*p)[10] = (int (*)[10])&(aa[0][col]);

   for(int i =0; i<10; i++)
      cout << *(p[i]) << endl;

   return 0;
}

与aa[row][2]的区别是使用一个指向长度为10的1d int数组的指针

int (*p)[10]
,有关
int (*p)[10]
的更多上下文,参见这个答案

p
保存一维数组的地址
{2, 3, 4, 5, 6, 7, 8, 9, 10, 11}
p+1
保存一维数组
{12, 13, 14, 15, 16, 17, 18, 19, 20, 21}
的地址。
*(p[1])
*(*(p+1))
访问一维数组的第一个值。


0
投票

如果您希望矩阵位于连续位置,请将其声明为一维数组并自行执行行和列计算:

int contiguous_matrix[81];

int& location(int row, int column)
{
  return contiguous_matrix[row * 9 + column];
}

您还可以迭代行的每一列:

typedef void (*Function_Pointer)(int&);

void Column_Iteration(Function_Pointer p_func, int row)
{
  row = row * MAXIMUM_COLUMNS;
  for (unsigned int column = 0; column < 9; ++column)
  {
    p_func(contiguous_matrix[row + column]);
  }
}

0
投票

对于静态声明的数组,您可以像连续一维数组一样访问它们,

p = matrix[0]
将为您提供第一行的第一列。然后可以像
p[i]
*(p+i)
p[current_raw * raw_size + current_column)
那样访问一维数组。

如果用

**p
表示 2D 数组,事情就会变得棘手,因为它将被解释为指向 1D 数组的指针数组。


0
投票

我不知道这是否是一个有效的解决方案,但通过这样做我可以获得专栏,

int arr[9][2] = { {2,  57}, {3,  66}, {4,  73}, {5,  76}, {6,  79}, {7,  81}, {8,  90}, {9,  96}, {10, 100}};

int c[18];
int co = 0;
for (auto & i : arr) {
    for (int j : i) {
        c[co++] = j;
    }
}

for (int i = 0; i < co; ++i) {
    if (i % 2 != 0)
        std::cout << c[i] << " ";
}

0
投票

使用 drop 和 stride 视图的 C++23 解决方案,在列元素上创建视图。

#include <ranges>
#include <print>
#include <vector>

int main()
{
    const auto nrColumns = 3;
    const auto nrRows = 3;
    const int matrix[nrRows][nrColumns] = { 1, 2, 3, 11, 22, 33, 111, 222, 333 };
    const auto values = std::span(matrix[0], nrRows * nrColumns);

    const auto columnIndex = 1;
    const auto columnView = values | std::views::drop(columnIndex) | std::views::stride(nrColumns);

    for(const auto& value : columnView)
    {
        std::print("{0}, ", value);
    }
}

退货

2, 22, 222, 

自己尝试一下:https://godbolt.org/z/bG5Md4zs7

© www.soinside.com 2019 - 2024. All rights reserved.