3

将多维数组传递给函数时,为什么 C++ 要求在参数 li 中指定除第一个维度之外的所有维度

4

4 回答 4

11

提出这个问题的更好方法是询问为什么 C++ 不需要指定第一个维度。

原因是对于所有数组,您不能将数组按值传递给函数。如果您尝试声明一个采用数组的函数,编译器会将声明调整为相应的指针类型。

这意味着您指定的维度并不重要,因为维度不构成函数签名的一部分。

例如,这些都声明了完全相同的函数。

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]);

因为调整外部数组维度以外的任何维度都会影响(至少)外部数组元素的大小,这意味着用于导航数组的指针算法必须改变。

于 2012-06-05T10:16:09.480 回答
0

如果你指的是静态分配,这很简单。因为内存块是连续的,这意味着内存单元一个接一个,编译器知道下一个单元在内存中的位置。

对于内存中的一维数组,如下所示:

http://cplusplus.com/doc/tutorial/arrays/arrays3.gif

对于内存中的二维数组,如下所示:

http://i.msdn.microsoft.com/dynimg/IC506192.png

于 2012-06-05T10:19:13.673 回答
0

例如int a[n][m]一个数组,它的类型是一个int长度数组m。换句话说,数组的长度是其类型的一部分。而对于所有的函数参数,编译器需要知道它的类型。

在 C++ 中没有多维数组之类的东西。它只是一个看起来像它的语法。inint a[4]int b[5]a 和 b 是不同的类型。

于 2012-06-05T10:10:15.937 回答
0

简而言之:编译器不需要维度,因为数组衰减为指针。但是编译器需要任何额外的维度来计算内存中的正确位置。

首先你需要知道 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 中的数组,尤其是(不规则的)多维数组是完全不同的。

于 2012-06-05T12:17:47.143 回答