引言
假设现在让你写一个能计算一系列值的平均值的C代码。如果这些数值存放于数组中,那就非常简单了,如果是作为函数的形参传进去呢?
va_list,va_start,va_arg,va_end
下面介绍一种解决上面问题的一个方法:可变参数列表——stdarg宏。
可变参数列表的实现是通过一个类型va_list和三个宏va_start,va_arg,va_end来实现的。这些定义位于stdarg.h头文件里面。
先上一段代码。
/*计算指定数量的平均值*/
#include <stdarg.h>
#include <stdio.h>
float average(int n_values,...)
{
va_list args;
int count;
float sum = 0;
va_start(args,n_values); /*准备访问可变参数*/
for(count=0;count<n_values;count++)
{
sum += va_arg(args,int);
}
va_end(args);/*访问完最后一个可变参数后需要调用宏va_end*/
return sum/n_values;
}
int main()
{
float final;
final = average(5,1,2,3,4,5);
printf("final = %f",final);
return 0;
}
小结用法
先声明一个va_list类型的变量args,要开始访问可变参数的时候要先调用va_start来初始化,然后使用va_arg函数返回这个参数的值,并使va_arg指向下一个可变参数。访问完毕最后一个可变参数就调用va_end。
在定义函数average的时候,函数参数列表中的省略号,它提示的是你要传递的变量的个数。在声明这个函数跟定义这个函数的时候都需要在参数列表里面加上这个...。在main函数里面调用average时在省略号的地方就需要填入你的实参。
va_start
va_start的第1个参数是va_list类型的变量,第2个参数是省略号前最后一个有名字的参数。(这样子它就知道可变参数是哪些了)。在上面的例子就是n_values。
va_arg
va_arg的第1个参数是va_list类型的变量,第2个参数是参数列表中下一个参数的类型。va_arg返回当前可变参数列表中的参数的值,并使va_arg指向下一个可变参数。在前面提到的va_start中,初始化过程把va_arg设置为指向可变参数部分的第1个参数。
va_end
va_end只有一个参数,就是va_list类型的变量。与va_start成对使用,当访问完毕最后一个可变参数之后,需要调用va_end。
注意
在va_arg中,char,int,float,类型的值实际上将作为 int或者 double类型的值传递给函数,所以你在va_arg中使用这些类型的时候应该要注意一下。