某些函数可以接受可变数量的参数。例如,printf()
和scanf_s()
函数。标准库stdarg.h
提供了编写自己的一些实现好的函数。具有可变数量参数的函数具有以下原型:
double average(double v1, double v2, ...);
省略号表示可变数量的参数可以跟在前两个固定参数之后。必须至少有一个固定参数,需要使用va_start()
,va_arg()
和va_end()
来处理参数。
第一个函数具有以下形式:
void va_start(va_list parg, last_fixed_arg);
va_start
表示变量参数start
。该函数接受两个参数:
- 一个类型为
va_list
的指针parg
- 最后一个固定参数的名称:
last_fixed_arg
。
va_list
类型是在stdarg.h
中定义的类型,它存储变量参数列表的信息。可以开始编写如下函数:
double average(double v1, double v2,...)
{
va_list parg; // 变量参数列表的指针
// 此处编写更多其它代码...
va_start( parg, v2);
// 此处编写更多其它代码...
}
va_start()
将变量parg
设置为指向传递给函数的第一个变量参数。必须确定每个变量参数的类型。average()
函数处理double
类型的参数。
以下代码显示了如何访问每个变量参数的值:
double average( double v1, double v2,...){
va_list parg; // 变量参数列表的指针
double sum = v1 + v2; // 累积参数的总和
double value = 0.0; // 参数值
int count = 2; // 参数数量的计数
va_start(parg,v2); // 初始化参数指针
while((value = va_arg(parg, double)) != 0.0)
{
sum += value;
++count;
}
va_end(parg); // 结束变量参数过程
return sum/count;
}
看看循环条件:
while((value = va_arg(parg, double)) != 0.0)
循环条件调用va_arg()
,va_arg()
的第一个参数是由va_start()
初始化的变量parg
。
第二个参数是参数类型的规范。va_arg()
函数返回 parg
通过值指定的当前参数的值。
当获得的参数值为0.0
时,循环结束:
va_end(parg); // 结束变量参数过程
va_end()
清理进程,它将parg
指针重置为NULL
。
示例代码
#include <stdio.h>
#include <stdarg.h>
double average(double v1, double v2, ...); // 函数声明
int main(void)
{
double v1 = 10.5, v2 = 2.5;
int num1 = 6, num2 = 5;
long num3 = 12L, num4 = 20L;
printf("Average = %.2lf\n", average(v1, 3.5, v2, 4.5, 0.0));
printf("Average = %.2lf\n", average(1.0, 2.0, 0.0));
printf("Average = %.2lf\n", average((double)num2, v2, (double)num1,
(double)num4, (double)num3, 0.0));
system("pause");
return 0;
}
// 用于计算两个或多个参数的平均值的函数
double average(double v1, double v2, ...)
{
va_list parg; // 变量参数列表的指针
double sum = v1 + v2; // 累积参数的总和
double value = 0.0; // 参数值
int count = 2; // 参数的数量
va_start(parg, v2); // 初始化参数指针
while ((value = va_arg(parg, double)) != 0.0)
{
sum += value;
++count;
}
va_end(parg); // 结束变量参数过程
return sum / count;
}
执行上面示例代码,得到以下结果:
Average = 5.25
Average = 1.50
Average = 9.10
复制va_list
stdarg.h
头文件中, va_start()
生成parg
的副本,如下所示:
va_list parg_copy;
va_copy(parg_copy, parg);