C++ 为什么多维数组中需要更高维度的维度范围?
据邮报报道,C++ 为什么多维数组中需要更高维度的维度范围?,c++,c,C++,C,据邮报报道, int数组[10][10]; void passFunc(int a[][10])/作为函数参数int a[][10]相当于int(*a)[10],意思是:a是指向10int数组的指针。在本例中,它不表示二维数组 如果较高维度留空,则编译器不可能知道指针a指向的数组长度,并且无法执行指针算术 C/C++中的数组是一种类型,但不是一级对象,它们在传递给函数时“衰减”为指向第一个元素的指针 int[10][10]是由10个int[10]数组组成的数组。。。函数声明: void foo
int数组[10][10];
void passFunc(int a[][10])/作为函数参数int a[][10]
相当于int(*a)[10]
,意思是:a
是指向10int
数组的指针。在本例中,它不表示二维数组
如果较高维度留空,则编译器不可能知道指针a
指向的数组长度,并且无法执行指针算术 C/C++中的数组是一种类型,但不是一级对象,它们在传递给函数时“衰减”为指向第一个元素的指针
int[10][10]
是由10个int[10]
数组组成的数组。。。函数声明:
void foo(int x[][10]);
typedef int IntArray10[10];
void bar(IntArray10 *x);
对于编译器,它们是相同的
因此,将2d数组传递给函数时,您传递的是指向第一个元素的指针(忽略第一个维度),但元素本身是数组,编译器需要知道其大小。另一种解释(数组到指针衰减):
假设我们有一个一维数组,我们这样使用它:
int array[10];
int i = array[3];
编译器必须知道在哪里可以找到数组[3]
。它知道需要跳过3个int
s才能到达array[3]
中的一个。所以它起作用了
但如果我们有一个二维数组
int array[2][5];
int i = array[1][1];
要在此处获取i
,编译器需要跳过多少int
s?它需要跳过整行,再加上一行。跳过一个很容易,因为我们知道一个int
的大小。但是我们还需要知道数组中行的大小,行的大小由类型的大小*每行的列数决定。这是一种看待它的方式,这解释了为什么需要后一个维度
让我们把它作为一个小小的脑筋急转弯,从一个维度进一步,到另一个维度
int array[2][2][2];
int i = array[1][1][1];
让我们把尺寸称为X,Y,Z
在这里,我们可以说我们有一个有限的三维空间int
s。这个单位当然是一个int
的大小。行的数量由Y定义,平面的数量由Z定义。这使得X成为基本单位,正如我们所说的,它的大小是1int
。三者的结合产生一个“点”
为了能够到达3D空间中的任何点,我们需要知道每个维度“停止”和下一个维度开始的位置。因此,我们需要:
用于遍历X维度的单位大小(int
)
每个平面(Y)的大小,以遍历Y标注
要遍历Z标注的平面数
同样,X已经给了我们,因为我们使用的是int
。但我们不知道每架飞机的大小,也不知道有多少架飞机。因此,我们需要指定除第一个维度以外的所有维度。这是一般规律
这也解释了为什么这个问题需要比指针衰减更详细的解释,因为一旦你达到2维以上,你仍然需要知道它是如何工作的。
换句话说,您需要总大小(维度的乘积)不溢出,并且需要每个大小的维度能够使用连续的[]
索引。这是必需的,因为在C中不存在多维数组的概念。
我们可以定义任何东西的数组,甚至是另一个数组。最后一个可以看作是多维数组。
现在考虑一个二维数组:
int arrray[5][4];
这将被解释为5个元素的数组,每个元素是4个int
的数组
在内存中,布局是顺序的:首先是第一个数组的4个元素,然后是第二个,依此类推,直到第五个数组的4个元素。
要访问第三个数组的第二个元素数组[2][1]
编译器必须跳过前两个数组,但要这样做,需要知道要跳过多少个元素
即,从数学上讲,第三个数组的第二个元素的地址为:
//pElement2Array3 points the 2nd element of the 3rd array.
//Note that 4 is the number of elements of the base dimension
int *pElement2Array3 = &array[0] + (2 * 4) + 1;
(注意:术语(2*4)+1
不会乘以sizeof(int)
,因为这是通过指针算法自动完成的。)
当使用寻址数组[2][1]
,时,编译器会自动执行上面的数学运算,但要执行它,编译器必须知道基数组中有多少元素(可能是数组的数组…,这与参数int a[]中的“[]”相反
,该函数不接受二维数组,而是指向一维数组的指针-其原型与
void passFunc(int (*a)[10])
与所有数组一样,array
可以衰减为指向其第一个元素的指针。
与往常一样,该指针是&数组[0]
,在本例中,它是指向具有十个int
s的数组的指针,即int(*)[10]
因此,您不需要指定“更高的维度”,而是参数是指向十个元素的数组的指针,而不是二维数组
(您不能让a
成为指向未指定大小数组的指针,因为编译器需要知道a[1]
相对于a[0]
的位置,也就是说,它需要知道sizeof(*a)
)简单地说,因为多维数组从右向左“增长”。你可以这样想:
int array[10];
int i = array[3];
int-arr[a]
是a
整数的数组
int-arr[b][a]
是一个b
整数数组
等等
至于为什么在将数组传递给函数时可以省略最左边的维度,这是因为“数组衰减”。6.7.6.3/7规定:
作为“类型数组”的参数声明应调整为
“指向类型的限定指针”
也就是说,如果将函数参数声明为int param[