【发布时间】:2012-06-05 10:07:02
【问题描述】:
当一个多维数组传递给一个函数时,为什么C++要求在参数li中指定除第一个维度之外的所有维度
【问题讨论】:
-
因为函数不能接受数组参数。
标签: c++ arrays multidimensional-array
当一个多维数组传递给一个函数时,为什么C++要求在参数li中指定除第一个维度之外的所有维度
【问题讨论】:
标签: c++ arrays multidimensional-array
问这个问题的更好方法是问为什么 C++ 不需要指定第一个维度。
原因是对于 all 数组,您不能将数组按值传递给函数。如果您尝试声明一个采用数组的函数,编译器会将声明调整为相应的指针类型。
这意味着您指定的维度无关紧要,因为该维度不构成函数签名的一部分。
例如,这些都声明了完全相同的函数。
void f(int *p);
void f(int p[]);
void f(int p[10]);
void f(int p[100]);
在函数中导航p 指向的数组时,编译器需要的唯一信息是数组元素的大小,在这种情况下为sizeof(int)。
对于更复杂的数组,同样适用。这些都是一样的:
void g(Type p[][10][20]);
void g(Type (*p)[10][20]);
void g(Type p[10][10][20]);
void g(Type p[99][10][20]);
但这些都不同于:
void g(Type p[][5][20]);
因为调整外部数组维度以外的任何维度都会影响(至少)外部数组元素的大小,这意味着导航数组的指针算法必须改变。
【讨论】:
例如int a[n][m] 是一个数组,其类型为int 长度为m 的数组。换句话说,数组的长度是其类型的一部分。而对于所有的函数参数,编译器需要知道它的类型。
c++ 中没有多维数组这种东西。它只是一个看起来像它的语法。在int a[4] 和int b[5] 中a 和b 是不同的类型。
【讨论】:
如果你指的是静态分配,这很简单。 因为内存块是连续的,这意味着内存单元一个接一个,编译器知道下一个单元在内存中的位置。
对于内存中的一维数组,如下所示:
http://cplusplus.com/doc/tutorial/arrays/arrays3.gif
对于内存中的二维数组,如下所示:
【讨论】:
简而言之:编译器不需要维度,因为数组衰减为指针。但是编译器需要任何额外的维度来计算内存中的正确位置。
首先你需要知道C/C++中的数组是内存中的线性连续对象。这是非常有效的。
由于 C/C++ 中的数组是内存中的线性连续对象,因此数组会衰减为指针。复制完整的数组将浪费时间和内存,并且不需要。指针是通过数组所需的任何东西。要遍历数组,您可以使用增量运算符或任何计算结果为数组中有效地址的计算。您可以在数组本身中设置分隔符,即字符串中的 '\0',或者将长度传递给函数 seperatley 以告诉您的代码数组的末尾在哪里。
对于多维数组,事情会稍微复杂一些。多维数组在内存中仍然只是一个线性连续的对象!但是编译器需要关于额外维度的信息来计算来纠正内存中的位置,想象一下:
char array[10][10]; // 0 - 99
正确:
// formal argument tells your compiler, that each column is 10 elements long
funca(int array[10][10]) {
// access to element 25 (2 * 10 + 4, the 10 is known through your formal argument, remember that an array is null based)
array[2][3] = 'x';
}
错误:
// formal argument tells your compiler, that ech colum is 5 elements long
funcb(int array[10][5]) {
// access to element 15 (2 * 5 * + 4, the 5 is known through your formal argument, remember that an array is null based)
array[2][3] = 'x';
}
注释(或警告): Java中的数组,尤其是(不规则的)多维数组完全不同。
【讨论】: