函数通过数组作为参数
1、对于一维数组来说,数组作为函数参数传递,实际上传递了一个指向数组的指针,在c编译器中,当数组名作为函数参数时,在函数体内数组名自动退化为指针。此时调用函数时,相当于传址,而不是传值,函数中对于数组的操作将会改变数组元素的值。
void foo(int *arr){} //或者 void foo(int arr[]){} //或者 void foo(int arr[3]){}
2、对于更高维数组来说,可以用数组名作为实参或者形参,在被调用函数中对形参数组定义时可以指定所有维数的大小,也可以省略第一维的大小说明。
下面以二维数组举例:
void fun(int array[3][10]); //或者 void fun(int array[][10]);
二者都是合法而且等价,但是不能把第二维或者更高维的大小省略,如下面的定义是不合法的:
void fun(int array[][]); //不合法
二维数组当作参数的时候,必须指明所有维数大小或者省略第一维的,但是不能省略第二维或者更高维的大小,这是由编译器原理限制的。编译器处理int p[m][n]数组时
如果要取 p[i][j] 的值(i>=0 && i<m && 0<=j && j < n),编译器是寻址的地址为: p + i*n + j
如果我们省略了n的值(第二维或者更高维的大小),编译器将获取不到 p[i][j] 的正确地址。
我们也可以声明两个参数指明各个维数,然后我们为二维数组手工寻址,这样就达到了将二维数组作为函数的参数传递的目的,根据这个思想,我们可以把维数固定 的参数变为维数随即的参数,例如:
void fun(int array[3][10]); void fun(int array[][10]); //变为: void fun(int **array, int m, int n);
在转变后的函数中,array[i][j]这样取值是错误的,因为编译器不能正确的为它寻址。
所以我们需要模仿编译器的行为把array[i][j]这样的式子手工转变为:*(*array + n*i + j);
在调用这样的函数的时候,需要注意一下,如下面的例子:
int a[3][3] = { {1, 1, 1}, {2, 2, 2}, {3, 3, 3}};
fun(a, 3, 3);
根据不同编译器不同的设置,可能出现warning 或者error,可以进行强制转换如下调用:
fun((int**)a, 3, 3);
(转自https://www.cnblogs.com/weixiaoyu/p/4371806.html)
函数返回数组
C 不支持函数在函数外返回函数的局部变量的地址,除非定义局部变量为 static 变量。
int* foo()
{ static int r[10];return r; }
还有一种写法
int arrSize = 10; //数组长度 int* foo() { int *r = (int*)malloc(arrSize*sizeof(int)); return r; }
经常看到Leetcode上这么声明一个函数
int* foo(int* arr, int arrSize, int* returnSize) { ... //int* r =(int*) malloc(10*sizeof(int)); //*returnSize = 10; //return r; } /* * int* foo表示函数返回数组 * int* arr表示传入的数组,因为C无法直接通过数组名获取数组长度,所以需要另外一个参数int arrSize作为arr的长度传入 * int* returnSize表示函数返回的数组的长度,参数类型一定是int*而不是int 因为只有传入参数的指针(int*)才能在函数中改变传入参数变量的值,int表示传入的仅仅是数值,无法改变原变量 */
浙公网安备 33010602011771号