【问题标题】:Passing a 2D Array to function in C++ [duplicate]将二维数组传递给 C++ 中的函数 [重复]
【发布时间】:2021-04-20 00:44:18
【问题描述】:

我尝试将二维数组传递给 C++ 中的函数,但我不明白:

//My array declaration:
int array[5][5]={{....}}; //I declared and filled the array with values
//My different function tries:
void passArr(int **array) //ERROR
void passArr(int *array[5]) //ERROR
void passArr(int *(*array)) //ERROR
void passArr(int (*(*array))) //ERROR
void passArr(int (*array)[5]) //WORKS

所有错误均为:[Error] cannot convert 'int (*)[5]' to 'int**' for argument '1' to 'void passArr(int**)'

为什么会出现错误,最重要的是,int *array[5] 和 int (*array)[5] 作为参数传递时有什么区别?

如果int (*array)[5] 有效,那么为什么int *(*array) 或int (*(*array))) 也无效?

【问题讨论】:

  • 围绕 C++ 类型系统的一种解决方法是改用结构:struct array5x5 { int data[5][5]; }; void passArr(array5x5 *array) { ... }。否则,请使用 C++ 类型,例如 std::array、std::vector... 您还可以使用 int (&array)[5][5] 之类的方式传递对数组的引用

标签: c++ arrays function


【解决方案1】:

在 C 和 C++ 中,二维数组是 Array-of-Arrays。二维数组的第一个元素是它包含的第一个一维数组。转换在C++ Standard - Array-to-pointer Conversion [conv.array]中指定

当您将 plain-old 二维数组声明为:

int array[5][5]

你有一个int[5] 数组。与任何数组一样,它在访问时转换为指向其第一个元素的指针。第一个元素是int[5] 的数组,所以结果类型是:

int (*)[5]

一个指向数组的指针 int[5]。所以对于名为array 的二维数组,即:

int (*array)[5]

【讨论】:

    【解决方案2】:

    它们只是不同的东西。从右到左阅读可能会有所帮助。

    int array[5][5]  -> array of array of int, could decay to pointer to array of int
    int (*array)[5]  -> pointer to array of int, could be converted from the above
    
    int **array      -> pointer to pointer to int
    int *(*array)    -> same as above
    int (*(*array))  -> same as above
    
    int *array[5]    -> array of pointer to int
    

    【讨论】:

    • 了解 C/C++ 有时就像指向 x 的指针一样,与 x 的数组相同,但有时却不同,这一点也很重要,例如在struct X {int *x; int y[20]} 或sizeof z。
    【解决方案3】:

    此外,在 “C++” 语言中,强烈建议使用众多 “容器类” 之一这个目的。或者也许是您自己设计的class。

    “简单指针”无法传达它指向“二维数组”,也无法传达其维度。它的工作描述范围是它知道如何指向“一堆字节,或者什么都没有”。

    但是,如果您改为向调用者提供一个类的引用,您的调用者现在可以“向类询问”它需要什么,“类会神奇地知道”。只需提交课程(X,Y),您要么得到正确答案,要么引发运行时异常。每一次......顺便说一句,高效。

    这是一种更加更强大的代码编写方式,这确实是发明 C++ 语言的原因。

    【讨论】:

      【解决方案4】:

      版本 1、3 和 4 都是相同的。版本 2 也与 1,3 和 4 相同,因为当将数组传递给函数时,数组会衰减为指针。

      第二版也可以写

      void passArr(int* array[5])
      

      这可能更清楚地显示了星号与类型的关联:它是一个由五个 int 指针组成的数组。随着数组衰减到一个指针,它变成了

      void passArr(int** array)
      

      都表示数组的入口是地址,指向另一个数组:

       [ * | * | * | * | * ]
         |    |    |    |   +-> [,,,,]
         |    |    |    +-> [,,,,]
      And so on.
      

      当每个条目是 5 个整数的数组,而不是指向一个整数的指针时,您所拥有的是一个数组(数组与指针有很多相似之处,但它们不是指针!)

      您的矩阵如下所示:

      [ [1,2,3,4,5], [6,,,,], [,,,,], [,,,,], [,,,,] ]
      

      因此,数组是指向 int[5] 的指针,而不是指向 int 的指针。这就是版本 5 中括号的作用:int (*array)[5]。这会将星号绑定到更接近数组的位置。

      【讨论】:

        猜你喜欢
        • 2013-01-18
        • 2013-03-28
        • 2018-12-08
        • 2021-05-10
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多