5. 数组作为函数的参数

函数的传参实质是传值,即函数的实参会赋值给函数的形参。

这节课我们来学习函数如何传递一个数组给调用函数。数组是不能够直接赋值给另一个数组,因此数组是不能够通过传值的方式传递给另一个函数。

那么如何来传递一个数组呢?答案就是实参传递数组的起始地址,形参用指针接收数组地址。数组名称的返回值就是数组的起始地址,类型为数据元素的类型的指针。

数组的返回类型

  1. 一维数组的数组名返回类型为 数据类型*
  2. 二维数组的数组名返回类型为 数据类型(*)[数组内一维数组元素个数]
  3. 三维数组同二维数组,其它多维数组以此类推。

示例

// 一维数组
int arr1[4];  // 表达式 arr1 的返回类型为 int*

// 二维数组
int arr2[3][4];  // 表达式 arr2 的返回类型为 int(*)[4]

// 三维数组
int arr3[2][3][4];  // 表达式 arr3 的返回类型为 int(*)[3][4]

如果定义函数时需要在形式参数中定义形参变量来接收数组数据。则可以按着上述类型的指针来指向实参数组,在 C 语言中,也可以用类似于数组定义的方式来定义形参变量。如:

说明:

一维数组示例

在函数内求一维数组的所有数据元素的和。

// 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_sum2arr1d_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_sum1arr2d_sum2arr2d_sum3 只是形参列表不同,三个函数的功能完全一样。

实验:

  1. 在上述一维数组中的示例中,在函数内部修改数组中的数据元素的值。然后在主函数内查看数据是否修改。
  2. 尝试使用三维数组完成上述示例中的实验。