Hoo*_*lum 33 c arrays parameters parameter-passing multidimensional-array
为什么我的参数不能
void example(int Array[][]){ /*statements*/}
Run Code Online (Sandbox Code Playgroud)
为什么我需要指定数组的列大小?比如说3
void example(int Array[][3]){/*statements*/}
Run Code Online (Sandbox Code Playgroud)
我的教授说它是强制性的,但我在学校开始之前编码,我记得当我把它作为我的参数时没有语法或语义错误?还是我错过了什么?
Mak*_*zin 33
在描述参数时,数组总是衰减成指向第一个元素的指针.
当你传递一个声明为int Array[3]函数的数组时void foo(int array[]),它会衰减成一个指向数组开头的指针,即int *Array;.顺便说一句,您可以将参数描述为int array[3]或int array[6]甚int *array至 - 所有这些都是等效的,您可以毫无问题地传递任何整数数组.
在阵列阵列(2D阵列)的情况下,它也会衰减到指向其第一个元素的指针,这恰好是一个单维数组,即我们得到的int (*Array)[3].
在此指定大小非常重要.例如,如果它不是强制性的,那么编译器就没有办法知道如何处理表达式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产生什么地址:提前Array2个字节(错误)推进地址或提前指针3* sizeof(int) * 2字节?
pen*_*ope 11
在C/C++中,甚至2-D数组也按顺序存储,在内存中依次存储.所以,当你有(在一个函数中):
int a[5][3];
int *head;
head = &a[0][0];
a[2][1] = 2; // <--
Run Code Online (Sandbox Code Playgroud)
您实际访问的元素a[2][1]是*(head + 2*3 + 1),顺序地,该元素在该0行的3个元素之后,以及该行的3个元素之后1,然后再一个索引.
如果你声明一个像这样的函数:
void some_function(int array[][]) {...}
Run Code Online (Sandbox Code Playgroud)
语法上,它不应该是一个错误.但是,当您尝试array[2][3]现在访问时,您无法分辨应该访问哪个元素.另一方面,当你有:
void some_function(int array[][5]) {...}
Run Code Online (Sandbox Code Playgroud)
你知道吗array[2][3],可以确定你实际上是在内存地址访问元素,*(&array[0][0] + 2*5 + 3) 因为函数知道第二个维度的大小.
还有另外一个选项,如前所述,您可以声明如下函数:
void some_function(int *array, int cols) { ... }
Run Code Online (Sandbox Code Playgroud)
因为这样,您使用与以前相同的"信息"调用函数 - 列数.您可以稍微不同地访问数组元素:您必须编写*(array + i*cols + j)通常写入的位置array[i][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;
}
Run Code Online (Sandbox Code Playgroud)