我们都用过 printf() 函数,函数的参数个数是不确定的,第一个参数一定是字符串。这种可变参数是如何实现的呢,我们今天就来学习下。

1 可变参数

首先,要实现可变参数必须依赖于头文件 stdarg.h。
其次,实现函数可变参数需要使用以下几个标示符:

  • va_list:参数集合
  • va_arg:取具体参数值
  • va_start:标识参数访问的开始
  • va_end:标识参数访问的结束

看了上面几个标示符完全不知道怎么用,没关系,下面通过一个例子讲解,就会明白。

2 实例分析

编写一个函数求 n 个数的平均值,将这 n 个数直接作为参数传递给函数。

// 44-1.c
#include<stdio.h>
#include<stdarg.h>
float average(int n, ...)	// n表示要计算n个数的平均数
{
    va_list args;			// args是可变参数的集合
    int i = 0;
    float sum = 0;
    va_start(args, n);		// 标识参数访问的开始
    for (i = 0; i < n; i++)
    {
        sum += va_arg(args, int);	// 取具体的参数值,类型为int
    }
    va_end(args);			// 标识参数访问的结束
    return sum/n;
}
int main()
{
    printf("%f\n", average(5, 1, 2, 3, 4, 5));
    printf("%f\n", average(4, 1, 2, 3, 4));
    return 0;
}

先看一下可变参数的限制

  • 可变参数必须从头到尾按照顺序逐个访问
  • 参数列表中至少要存在一个确定的命名参数
  • 可变参数函数无法确定实际存在的参数的数量
  • 可变参数函数无法确定参数的实际类型

再来解读一下上面的代码:
1)参数列表中至少有一个确定的命名参数,这里的确定的参数是数字的数量,也就是 int 型的 n。类似的,printf() 函数中第一个参数永远是字符串,字符串中的 %d,%f,%p 等的数量用来确定有几个参数。

2)可变参数函数无法确定参数的实际类型,所以在取具体参数时使用 va_arg(args, int) 来确定参数为 int,在 printf 函数中使用 %d,%f,%s 等也是用来确定参数的类型。

注意:va_arg 中如果指定了错误的类型,那么结果时不可预测的。同样的在 printf() 函数中如果将%p 写成了 %d 得到的结果也是错误的。

3 小结

1、可变参数的函数提供了一种更方便的函数调用方式
2、可变参数必须顺序访问,无法直接访问中间的参数值