如何将多维数组传递给 C 和 C 中的函数

新手上路,请多包涵
#include<stdio.h>
void print(int *arr[], int s1, int s2) {
    int i, j;
    for(i = 0; i<s1; i++)
        for(j = 0; j<s2; j++)
            printf("%d, ", *((arr+i)+j));
}

int main() {
    int a[4][4] = {{0}};
    print(a,4,4);
}

这适用于 C,但不适用于 C++。

错误:

 cannot convert `int (*)[4]' to `int**' for argument `1' to
`void print(int**, int, int)'

为什么它在 C++ 中不起作用?需要做出什么改变?

原文由 Moeb 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 523
1 个回答

如果你真的需要你的代码在 C 中运行,你要么需要:

  1. 按照 我关于 C 样式数组的另一个 非常长 且非常彻底的答案,在这里,或者:
  2. 从头开始,在 C 中构建您自己的多维数组容器。

但是,如果使用 C++,使用向量的向量确实是最好的选择!因此,我在这里的新答案:

如何 通过 std::vector<std::vector<int>>& 将多维数组传递给 C++ 中的函数

如果使用 C++,请使用 std::vector<>std::vector<> s!:

 // Example:
std::vector<std::vector<int>> array2d;

_注意:在我的 eRCaGuy_hello_world 存储 库中查看并运行下面使用的完整演示代码: array_2d_via_std_vector.cpp 。_

示例 1:通过引用传递它: std::vector<std::vector<int>>&

 // Version 2: demonstrate passing the type withOUT the `array2d_t` type above,
// and iterating via range-based for loops.
void print_array2d_2(const std::vector<std::vector<int>>& array2d)
{
    // Option 2: range-based for loops

    // Iterate over all rows
    size_t i_row = 0;
    for (std::vector<int> row : array2d)
    {
        // Iterate over all columns
        size_t i_col = 0;
        for (int val : row)
        {
            printf("array2d[%zu][%zu]=%i ", i_row, i_col, val);
            i_col++;
        }
        i_row++;
        printf("\n");
    }
    printf("\n");
}

您也可以 typedef 类型或使用 using 声明使类型更易于管理:

 using array2d_t = std::vector<std::vector<int>>;
using grid_t = array2d_t; // alternative alias for a 2D array

// OR with typedef:
typedef std::vector<std::vector<int>> array2d_t;
typedef array2d_t grid_t; // alternative alias for a 2D array

然后将其传递为 array2d_t&grid_t& 或其他。这是另一个例子:

 // Version 1: demonstrate passing using the `array2d_t` above, and iterating
// using regular for loops.
void print_array2d_1(const array2d_t& array2d)
{
    // Option 1: regular for loops

    // Iterate over all rows
    for (size_t i_row = 0; i_row < array2d.size(); i_row++)
    {
        // To get access to just a row, do this if you like
        // const std::vector<int>* row = &array2d[i_row];
        // row->size();

        // Iterate over all columns
        for (size_t i_col = 0; i_col < array2d[i_row].size(); i_col++)
        {
            printf("array2d[%zu][%zu]=%i ",
                i_row, i_col, array2d[i_row][i_col]);
        }
        printf("\n");
    }
    printf("\n");
}

生成数组

可以在构建时生成数组:

     // a regular 2 x 3 2D grid or array
    array2d_t array2d_1 = {
        {11, 12, 13},
        {14, 15, 16},
    };
    print_array2d_1(array2d_1);
    print_array2d_2(array2d_1);
    printf("-------------\n\n");

使用向量的向量 ( std::vector<std::vector<int>> ) 还具有允许您拥有非均匀多维数组的好处。例如:一个有 3 行,第一行和最后一行 3 列,但中间行 4 列的数组:

     // Notice that having varying numbers of columns in each row in
    // `std::vector<>`-based 2D arrays is fine!
    array2d_t array2d_2 = {
        {1, 2, 3},
        {4, 5, 6, 7},
        {8, 9, 10},
    };
    print_array2d_1(array2d_2);
    print_array2d_2(array2d_2);
    printf("-------------\n\n");

您还可以在构造时预先设置数组的大小以具有一定数量的行和列,这样您就可以在构造 通过 [][] 运算符填充它,如下所示:

     constexpr size_t NUM_ROWS = 3;
    constexpr size_t NUM_COLS = 4;
    // By default, this creates a `NUM_ROWS x NUM_COLS` array with all zeros in
    // it, since that is the default value for type `int` when called as a
    // constructor-like default initializer, as in `int()`, which
    // performs "value initialization". See my Q:
    // https://stackoverflow.com/q/72367123/4561887
    array2d_t array2d_4(NUM_ROWS, std::vector<int>(NUM_COLS));
    // Let's just fill in a few of the values with non-zeros, as an example
    array2d_4[0][0] = 1;
    array2d_4[1][1] = 2;
    array2d_4[2][2] = 3;
    array2d_4[2][3] = 4;
    // array2d_4[3][3] = 5; // UNDEFINED BEHAVIOR! OUT OF ROW BOUNDS! Results
    //                      // in: `Segmentation fault (core dumped)`
    print_array2d_1(array2d_4);
    print_array2d_2(array2d_4);
    printf("-------------\n\n");

这是上面代码中最后一个打印输出的样子:

 array2d[0][0]=1 array2d[0][1]=0 array2d[0][2]=0 array2d[0][3]=0
array2d[1][0]=0 array2d[1][1]=2 array2d[1][2]=0 array2d[1][3]=0
array2d[2][0]=0 array2d[2][1]=0 array2d[2][2]=3 array2d[2][3]=4

array2d[0][0]=1 array2d[0][1]=0 array2d[0][2]=0 array2d[0][3]=0
array2d[1][0]=0 array2d[1][1]=2 array2d[1][2]=0 array2d[1][3]=0
array2d[2][0]=0 array2d[2][1]=0 array2d[2][2]=3 array2d[2][3]=4

-------------

请记住:如果您在数组外部进行索引,使用大括号运算符( [] ;又名: operator[] )不会自动为新成员分配新空间。相反,这是 _未定义的行为_,将导致分段错误!请参见此处: https ://en.cppreference.com/w/cpp/container/vector/operator_at(已添加重点):

std::map::operator[] 不同, 此运算符从不向容器中插入新元素。通过此运算符访问不存在的元素是 未定义的行为

使用 .resize() 更改大小,或使用 .push_back() 在向数组添加新元素时自动增长数组。

参考

  1. 在我的 eRCaGuy_hello_world 存储 库中查看上面使用的完整演示代码: array_2d_via_std_vector.cpp

原文由 Gabriel Staples 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题