我在一本书中读到,int f (int P[2][4])
无法接受A[2][3]
,但B[3][4]
没问题。这是什么原因?
特别是当我们使用指针创建动态分配时,这应该不是问题。
谢谢
答案 0 :(得分:5)
原因是 int f(int P [2] [4]); 是...的同义词 int f(int(* P)[4]); 函数声明中的第一个维度就是注释。
答案 1 :(得分:4)
原因是函数参数从未真正具有数组类型。编译器处理声明
int f(int P[2][4]);
好像它真的说了
int f(int (*P)[4]);
P
是指向四个int
的数组的指针。类型int [3][4]
衰减到相同类型。但类型int [2][3]
会衰减为int (*)[3]
类型,而不兼容。
动态分配完全是另一回事,无论你怎么做,它都可能不涉及数组数组类型。 (指针数组,更有可能。)
答案 2 :(得分:1)
不允许这样做的原因,因为f(int P[2][4])
变为f(int (*P)[4])
,因此您可以将int B[3][4]
传递给int (*B)[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
它将接受所有二维数组!
答案 3 :(得分:1)
在C和C ++中,如果指定一个函数需要二维数组,那么必须给它一个明确的列大小(第二个[]
)。行大小(第一个[]
)是可选的。
答案 4 :(得分:1)
它与内存布局有关系。第一个数字基本上是您的行数,第二个数字是每行中有多少个元素。行直接放在一起。因此,偏移量由行中元素的数量乘以前面的行数确定。编译的函数将基于4个元素计算行偏移。当您传递具有另一行长度的数组时,这些计算将是错误的。
答案 5 :(得分:0)
第二个参数定义了2d数组类型,因为它与每列中的元素数量有所不同。
第一个参数只定义数组的大小,因为你可以向该函数发送更长的数组,就像传递参数类型:int * [3]类似于将大小为10的1d数组传递给函数期望得到更小尺寸的数组 - 这在c ++中是合法的。