離家不遠

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

函数通过数组作为参数

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表示传入的仅仅是数值,无法改变原变量
*/

 

posted on 2020-10-23 14:31  離家不遠  阅读(1693)  评论(0)    收藏  举报