5. 数组作为函数的参数
函数的传参实质是传值,即函数的实参会赋值给函数的形参。
这节课我们来学习函数如何传递一个数组给调用函数。数组是不能够直接赋值给另一个数组,因此数组是不能够通过传值的方式传递给另一个函数。
那么如何来传递一个数组呢?答案就是实参传递数组的起始地址,形参用指针接收数组地址。数组名称的返回值就是数组的起始地址,类型为数据元素的类型的指针。
数组的返回类型
- 一维数组的数组名返回类型为
数据类型*。 - 二维数组的数组名返回类型为
数据类型(*)[数组内一维数组元素个数]。 - 三维数组同二维数组,其它多维数组以此类推。
示例
// 一维数组
int arr1[4]; // 表达式 arr1 的返回类型为 int*
// 二维数组
int arr2[3][4]; // 表达式 arr2 的返回类型为 int(*)[4]
// 三维数组
int arr3[2][3][4]; // 表达式 arr3 的返回类型为 int(*)[3][4]
如果定义函数时需要在形式参数中定义形参变量来接收数组数据。则可以按着上述类型的指针来指向实参数组,在 C 语言中,也可以用类似于数组定义的方式来定义形参变量。如:
- 接收一维数组 arr1 的形参变量可以写成
int * parr1、int parr1[]或int parr1[3]。 - 接收二维数组 arr2 的形参变量可以写成
int (* parr2)[4]、int parr2[][4]或int parr2[3][4]。 - 接收三维数组 arr3 的形参变量可以写成
int (* parr3)[3][4]、int parr3[][3][4]或int parr3[2][3][4]。
说明:
- 数组的形式参数写成数组形式时,最高维度的元素个数可以省略不写。
- 数组传递的实质的传址,在函数内部可以对原数组进行修改,如果不需要修改可以为形参变量的类型前加入
const关键字修饰。 - 接收数组的形参无论如何写法本质都是指针,不是数组,因此 sizeof 运算符得到的都是一个指针的字节数。
一维数组示例
在函数内求一维数组的所有数据元素的和。
// filename: array1d_as_arg.c
#include <stdio.h>
// 参数使用指针写法
void arr1d_sum1(int * parr1d, int arr_size)
{
int i, sum = 0;
printf("sizeof(parr1): %ld\n", sizeof(parr1d));
for (i = 0; i < arr_size; i++) {
sum += parr1d[i];
}
printf("数据内数据元素的和是: %d\n", sum);
}
// 参数使用类似于数组写法,不给定数据个数
void arr1d_sum2(int parr1d[], int arr_size)
{
int i, sum = 0;
printf("sizeof(parr1): %ld\n", sizeof(parr1d));
for (i = 0; i < arr_size; i++) {
sum += parr1d[i];
}
printf("数据内数据元素的和是: %d\n", sum);
}
// 参数使用类似于数组写法,给定数据个数
void arr1d_sum3(int parr1d[4], int arr_size)
{
int i, sum = 0;
printf("sizeof(parr1): %ld\n", sizeof(parr1d));
for (i = 0; i < arr_size; i++) {
sum += parr1d[i];
}
printf("数据内数据元素的和是: %d\n", sum);
}
int main(int argc, char * argv[]) {
int arr1[4] = {1, 2, 3, 4};
arr1d_sum1(arr1, 4);
arr1d_sum2(arr1, 4);
arr1d_sum3(arr1, 4);
return 0;
}
编译和运行结果如下:
weimingze@mzstudio:~$ gcc -o array1d_as_arg array1d_as_arg.c
array1d_as_arg.c: In function ‘arr1d_sum2’:
array1d_as_arg.c:19:42: warning: ‘sizeof’ on array function parameter ‘parr1d’ will return size of ‘int *’ [-Wsizeof-array-argument]
19 | printf("sizeof(parr1): %ld\n", sizeof(parr1d));
| ^
array1d_as_arg.c:16:21: note: declared here
16 | void arr1d_sum2(int parr1d[], int arr_size)
| ~~~~^~~~~~~~
array1d_as_arg.c: In function ‘arr1d_sum3’:
array1d_as_arg.c:30:42: warning: ‘sizeof’ on array function parameter ‘parr1d’ will return size of ‘int *’ [-Wsizeof-array-argument]
30 | printf("sizeof(parr1): %ld\n", sizeof(parr1d));
| ^
array1d_as_arg.c:27:21: note: declared here
27 | void arr1d_sum3(int parr1d[4], int arr_size)
| ~~~~^~~~~~~~~
weimingze@mzstudio:~$ ./array1d_as_arg
sizeof(parr1): 8
数据内数据元素的和是: 10
sizeof(parr1): 8
数据内数据元素的和是: 10
sizeof(parr1): 8
数据内数据元素的和是: 10
在使用 gcc 编译时,在 arr1d_sum2 和 arr1d_sum3 函数中,形参给出了数组的写法,但时间 sizeof 运算会给出警告,原因是它们不是数组,且 sizeof 返回的数据长度都是 8。
上述三个函数的形式参数的写法看似不同,实质确是完全一样的,三个函数的功能也完全一样。
二维数组示例
在函数内求二维数组的所有数据元素的和。
// filename: array2d_as_arg.c
#include <stdio.h>
// 参数使用指针写法
void arr2d_sum1(int (*parr2d)[4], int row, int col)
{
int r, c, sum = 0;
printf("sizeof(parr1): %ld\n", sizeof(parr2d));
for (r = 0; r < row; r++)
for (c = 0; c < col; c++)
sum += parr2d[r][c];
printf("数据内数据元素的和是: %d\n", sum);
}
// 参数使用类似于数组写法,不给定数据个数
void arr2d_sum2(int parr2d[][4], int row, int col)
{
int r, c, sum = 0;
printf("sizeof(parr1): %ld\n", sizeof(parr2d));
for (r = 0; r < row; r++)
for (c = 0; c < col; c++)
sum += parr2d[r][c];
printf("数据内数据元素的和是: %d\n", sum);
}
// 参数使用类似于数组写法,给定数据个数
void arr2d_sum3(int parr2d[3][4], int row, int col)
{
int r, c, sum = 0;
printf("sizeof(parr1): %ld\n", sizeof(parr2d));
for (r = 0; r < row; r++)
for (c = 0; c < col; c++)
sum += parr2d[r][c];
printf("数据内数据元素的和是: %d\n", sum);
}
int main(int argc, char * argv[]) {
int arr2[3][4] = {{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}};
arr2d_sum1(arr2, 3, 4);
arr2d_sum2(arr2, 3, 4);
arr2d_sum3(arr2, 3, 4);
return 0;
}
运行结果如下:
weimingze@mzstudio:~$ gcc -o array2d_as_arg array2d_as_arg.c
... 此处依旧会报告警告,请自行查看!
weimingze@mzstudio:~$ ./array2d_as_arg
sizeof(parr1): 8
数据内数据元素的和是: 78
sizeof(parr1): 8
数据内数据元素的和是: 78
sizeof(parr1): 8
数据内数据元素的和是: 78
上述三个函数 arr2d_sum1、arr2d_sum2、arr2d_sum3 只是形参列表不同,三个函数的功能完全一样。
实验:
- 在上述一维数组中的示例中,在函数内部修改数组中的数据元素的值。然后在主函数内查看数据是否修改。
- 尝试使用三维数组完成上述示例中的实验。