在函数间传递数组

数组也可以作为函数的参数进行传递,我们将求平均值的过程封装为一个函数,下面是一个可能的版本。

#include <stdio.h>

float average(int datas[6])
{
    int sum = 0;
    for (int i = 0; i < 6; ++i)
        sum += datas[i];
    return (float)sum / 6;
}

int main()
{
    int datas[6] = { 97, 88, 76, 45, 90, 92 };
    printf("avg=%.2f\n", average(datas));
    return 0;
}

glimix.com

函数average的实现有很大的缺陷,它仅是看起来接收一个有6个元素的数组参数,而实际上同类型任意数量的数组都可以。元素个数小于6时,存在数组访问越界的问题;元素个数多于6时,则仅计算前6个,计算结果不正确 ,你可能想到了基于sizeof的第二版实现。

ZYF

#include <stdio.h>

float average(int datas[6])
{
    int count = sizeof(datas) / sizeof(datas[0]);
    int sum = 0;

    for (int i = 0; i < count; ++i)
        sum += datas[i];

    return (float)sum / count;
}

int main()
{
    int datas[6] ={97, 88, 76, 45, 90, 92};
    printf("avg=%.2f\n", average(datas));
    return 0;
}

glimix.com

为了应对不同大小的数组,元素个数count是在函数体内通过sizeof计算的,不过这并不正确,count的值始终是1;接下来,我们试着将count的计算搬到main函数中。

int datas[6] = { 97, 88, 76, 45, 90, 92 };
int count = sizeof(datas) / sizeof(datas[0]);  // count = 6;

此时count的计数值是正确的,这说明数组传递给函数后发生了变化,使得sizeof再也计算不出原数组的字节数,即average中的sizeof(datas)不等于main中的sizeof(datas)。这个变化就是数组传递到函数后,退化为了相应的指针类型,而数组的大小(维度)信息被丢弃了。因此在向函数传递数组参数时,元素个数通常需要作为额外的参数进行传递。我们之前的函数声明,看似包含了元素个数,实则没用。

float average(int scores[6]);   // 数组的大小信息被丢弃,6根本没意义。

把6丢掉,这相当于

float average(int scores[]);    // 变量名后跟[],指示函数这个参数是个数组类型

由于退化丢失了大小信息,但我们可以通过补充额外的参数进行传递。

float average(int scores[], int size);

现在可以这样改写程序

#include <stdio.h>

// 1: 数组的大小信息被丢弃,因此写成 int[] 形式
// 2:数组元素个数作为额外的参数进行传递。
float average(int datas[], int count)
{
    float sum = 0;
    for (int index = 0; index < count; ++index)
        sum += datas[index];
    return sum / count;
}

int main()
{
    int da[6] = { 97, 88, 76, 45, 90, 92 };
    int db[9] = { 68, 79, 58, 90, 77, 79, 83, 86, 75 };

    printf("avg1=%.2f\n", average(da, 6));
    printf("avg2=%.2f\n", average(db, sizeof(db) / sizeof(int)));

    return 0;
}

glimix.com

数组作为一种集合类型,函数可以接收它,却不能返回数组!

glimix.com

ZYF

陕ICP备2025078817号-1 陕公网安备61011202001108号