为什么我的参数不能是
void example(int Array[][]){ /*statements*/}为什么需要指定数组的列大小?例如,3
void example(int Array[][3]){/*statements*/}我的教授说这是必修课,但我在开学前就开始编码了,我记得当我把这个作为我的参数时,没有语法或语义错误?还是我错过了什么?
发布于 2012-10-10 14:59:17
当涉及到描述参数时,数组总是衰减为指向其第一个元素的指针。
当您将一个声明为int Array[3]的数组传递给函数void foo(int array[])时,它会衰减为指向数组开头的指针,即int *Array;。顺便说一句,你可以把一个参数描述为int array[3]或int array[6],甚至int *array --所有这些都是等价的,你可以毫无问题地传递任何整数数组。
在数组(2D数组)的情况下,它也衰减为指向其第一个元素的指针,这恰好是一个一维数组,即我们得到int (*Array)[3]。
在这里指定大小很重要。例如,如果它不是强制性的,编译器将无法知道如何处理expression Array[2][1]。
在一个连续的内存块(int Array[2][3]是一个连续的整数块)中,编译器需要计算我们需要的项的偏移量,这对于指针来说应该很容易。如果a是一个指针,那么a[N]将扩展为start_address_in_a + N * size_of_item_being_pointed_by_a。在函数中使用表达式Array[2][1]的情况下(我们想访问这个元素),Array是一个指向一维数组的指针,同样的公式也适用。最后一个方括号中的字节数是查找size_of_item_being_pointed_by_a所必需的。如果我们只有Array[][],就不可能找到它,因此不可能取消对我们需要的数组元素的引用。
如果没有大小,指针算法将不适用于数组的数组。Array + 2会产生什么地址:将Array中的地址提前2个字节(错误),还是将指针提前3* sizeof(int) * 2个字节?
发布于 2012-10-10 15:19:09
在C/C++中,即使是二维数组也是按顺序存储在内存中的。因此,当您拥有(在单个函数中):
int a[5][3];
int *head;
head = &a[0][0];
a[2][1] = 2; // <--使用a[2][1]实际访问的元素是*(head + 2*3 + 1),因为该元素依次位于0行的3个元素和1行的3个元素之后,然后是更多的索引。
如果你像这样声明一个函数:
void some_function(int array[][]) {...}从语法上讲,它不应该是一个错误。但是,当您现在尝试访问array[2][3]时,您不知道应该访问哪个元素。另一方面,当你有:
void some_function(int array[][5]) {...}您知道,使用array[2][3],可以确定您实际访问的是内存地址为*(&array[0][0] + 2*5 + 3) 的元素,因为函数知道第二维的大小。
如前所述,还有另一个选项,您可以像这样声明一个函数:
void some_function(int *array, int cols) { ... }因为通过这种方式,您将使用与前面相同的“信息”--列数来调用函数。然后,您访问数组元素的方式有点不同:您必须在通常编写array[i][j]的地方编写*(array + i*cols + j),因为array现在是指向整数的指针(而不是指向指针)。
当您声明这样的函数时,您必须小心使用为数组实际声明的列数来调用它,而不仅仅是使用它。所以,举个例子:
int main(){
int a[5][5];
int i, j;
for (i = 0; i < 3; ++i){
for (int j=0; j < 3; ++j){
scanf("%d", &a[i][j]);
}
}
some_function(&a[i][j], 5); // <- correct
some_function(&a[i][j], 3); // <- wrong
return 0;
}发布于 2020-02-12 01:38:56
C 2018 6.7.6.2规定了数组声明符的语义,第1段给出了对它们的约束,包括:
元素类型不能是不完整或函数类型。
在像void example(int Array[][])这样的函数声明中,Array[]是一个数组声明符。因此,它必须满足元素类型不能不完整的约束。它在声明中元素类型是int [],这是不完整的,因为没有指定大小。
对于将要调整为指针的参数,C标准没有根本原因不能消除这种约束。生成的类型int (*Array)[]是一个合法声明,被编译器接受,并且可以以(*Array)[j]的形式使用。
但是,声明int Array[][]表明Array至少与一个二维数组相关联,因此应以Array[i][j]的形式使用。即使声明int Array[][]被接受并调整为int (*Array)[],使用它作为Array[i][j]也是不可能的,因为下标运算符要求其指针操作数是指向完整类型的指针,而这一要求是不可避免的,因为它是计算元素地址所必需的。因此,保持对数组声明符的约束是有意义的,因为它与预期的表达式一致,即参数将是一个二维数组,而不仅仅是指向一个一维数组的指针。
https://stackoverflow.com/questions/12813494
复制相似问题