将数组作为参数传递

4
我在一本书中读到,int f (int P[2][4]) 不能接受 A[2][3],但可以接受 B[3][4]。这是什么原因呢?特别是当我们使用指针创建动态分配时,这应该不是一个问题。谢谢。
6个回答

5
原因是int f(int P[2][4]);和int f(int (*P)[4]);是同义词,函数声明中的第一个维度只是注释。

+1. 但是可变参数函数有一个令人惊讶的例外。请参阅https://dev59.com/uHM_5IYBdhLWcg3wfTS7 :) - Johannes Schaub - litb
@沮丧的程序员:他不是来自IITB。他是litb(let-it-be) :)很高兴在SO上看到James Kanze回答问题 :) - Prasoon Saurav

4
原因在于函数参数实际上从未具有数组类型。编译器将声明视为指向数组的指针,即使它看起来像数组类型。
int f(int P[2][4]);

仿佛它真的是这样说的。
int f(int (*P)[4]);

P 是一个指向包含四个 int 的数组的指针。类型 int [3][4] 会衰减为相同的类型。但是类型 int [2][3] 衰减为类型 int (*)[3],它不兼容。

动态分配是完全不同的问题,无论如何都可能不涉及数组类型。 (更可能是指针数组。)


@Ben 那么参数类型将是引用到数组的数组。这不是与引用到类类型不同的数组类型。 - aschepler
我并不是说你的答案是错的,我只是提到了另一个非常相似但值得一提的情况(在我看来)。 - Ben Voigt

1
不允许的原因是,因为 f(int P[2][4]) 变成了 f(int (*P)[4]),所以可以传递能够转化成 int (*B)[4]int B[3][4],但是无法将 int A[2][3] 转化成 int (*A)[4],因此后者将不被 f(int (*P)[4]) 接受。
类型 int (*)[3]int (*)[4] 不兼容。它们之间无法相互转换!
然而,有一个解决方案。您可以这样做:
 template<size_t M, size_t N>
 int f(int (&P)[M][N])
 {
      //Use M and N as dimensions of the 2D array!
 }

 //Usage
 int A[2][3];
 f(A); //M becomes 2, N becomes 3

 int  B[3][4];
 f(B); //M becomes 3, N becomes 4

它将接受所有二维数组!


2
问题是“为什么不可能?”,而不是“如何避免?” - Null Set

1
在C和C++中,如果您指定一个函数接受2-D数组,则必须给出显式的列大小(第二个[])。行大小(第一个[])是可选的。

1

这与内存布局有关。第一个数字基本上是您的行数,第二个数字是每行中有多少元素。行直接放置在彼此之后。因此,它们的偏移量取决于前面行的元素数量乘以行数。编译函数将基于4个元素计算行偏移量。当您传递具有不同行长度的数组时,这些计算将是错误的。


0

第二个参数定义了2D数组的类型,因为每列中有多少元素是不同的。

第一个参数仅定义了数组的大小,由于您可以将更长的数组发送到该函数,就像传递类型为int * [3]的参数一样,这类似于将大小为10的1D数组传递给期望获得较短大小的数组的函数 - 这在C ++中是合法的。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接