前言
上篇文章我们介绍了指针数组与数组指针的定义与使用,那么我们平常在写代码的时候,难免会用到把数组或者指针当作参数传给函数使用。数组又分为一维数组和二维数组,甚至更高维,但一维和二维是最常使用的,同样,指针也分为一级指针、二级指针,还有更高级指针,但一级和二级指针最常用。这里只介绍最常使用的一维和二维数组传参,一级和二级指针传参。
1.一维数组传参
//一维数组传参
void test(int arr[]);
void test(int arr[10]);//[]内数字可写可不写
void test(int* arr);
void test2(int* arr[20]);
void test2(int** arr);//arr2是首元素的地址,即int* 的地址,也就是一个二级指针
int main()
{
int arr[10];
int *arr2[20];//存放指针的数组,也就是存放 int* 的数组
test(arr);
test2(arr2);//arr2是首元素的地址,即int*的地址,也就是一个二级指针
return 0;
}
解释:一维数组传参,当类型是简单的int、char数组不是指针数组类型时,函数的形参可以直接用int arr[]来接收参数,[]内数字可写可不写。当类型是指针数组时,例如是int* arr2[20],函数传参实参是arr2,arr2是数组名,所以arr2是数组首元素的地址,即int * 的地址,也就是一个二级指针,函数的形参也需要用一个二级指针来接收参数,所以可以使用int * arr[20]和int** arr二级指针作为形参。
2.二维数组传参
//二维数组传参
void test(int arr[3][5]);
void test(int arr[][5]);
void test(int arr[][]);//错的,行能省略但列不可省略
void test(int* arr);//错的,此时是一维数组
void test(int* arr[5]);//错的,此时是指针数组,既不是整形二维数组,也不是指针
void test(int(*arr)[5]);
void test(int** arr);//错的,传的是一行一维数组,不是二级数组
int main()
{
int arr[3][5];
test(arr);//二维数组的数组名代表的是一个指向行的指针,也就是指向二维数组第一行的地址。
return 0;
}
解释:二维数组的数组名arr是一个指向行的指针,也就是指向二维数组第一行的地址,arr+1就是指向二维数组第二行的地址。二维数组定义时可以省略行,但不可以省略列,所以函数形参可以是int arr[3][5]和int arr[][5],但不可以是int arr[][]。除了用数组的形式作为形参,也可以使用指针数组作为形参,即可以使用int( * arr)[5]作为形参,但不可以使用int * arr[5]和int** arr作为形参,因为int * arr[5]是一个指针数组,而不是数组指针,二维数组的数组名是一个指向行的指针,不是二维数组,所以不能用int** arr作为形参。
3.一级指针传参
//一级指针传参
void test(int *p);
int main()
{
int arr[10] = { 0 };
int* p = arr;
test(arr);
test(p);
int a = 1;
int* p1 = &a;
test(&a);
test(p1);
return 0;
}
解释:数组名就是一个指向首元素的地址,一维数组名就是一个一级指针,&变量名也是一级指针,可以直接使用int *p作为函数形参。
4.二级指针传参
//二级指针传参
void test(int **p);
int main()
{
int a = 1;
int* p = &a;
int** p1 = &p;//二级指针:存放一级指针变量的地址
test(p1);
test(&p);//传一级指针的地址
int* arr[10];
test(arr);//传指针数组的数组名
return 0;
}
解释:&一级指针变量名 就是一个二级指针,指针数组的数组名也是一个二级指针,二级指针存放的是一级指针变量的地址,函数形参可以使用int **p的形式。
5.总结
不管是数组传参还是指针传参,函数的形参类型都要与实参类型一一对应,例如不能使用int** arr形参接收int arr[3][5]的arr指向行的指针。如果实在不理解,就可以根据实参类型来定义形参的类型,这样在编译时不会出错。介绍完数组参数和指针参数,下篇文章将介绍指针进阶的最后一篇,也是最重要的,即函数指针。