stdarg.h头文件提供一种方法定义参数数量可变的函数。这种函数的原型有一个形参列表,列表中至少有一个形参后面跟有省略号:
void f1(int n, ...) //有效
int f2(int n, float x, int k, ...) //有效
double f3(...) //无效
在下面的表中,parmN是省略号前面的最后一个形参的标识符。在上面的例子中,第1种情况的parmN为n,第2种情况的parmN为k。
头文件中声明了va_lis类型表示储存形参列表中省略号部分的形参数据对象。下面列出了3个带可变参数列表的函数中用到的宏。在使用这些宏之前要声明一个va_list类型的对象。
| 可变参数列表宏 | |
| 宏 | 描述 |
| void va_start(va_list ap, parmN) | 该宏在va_arg()和va_end()使用ap之前初始化ap,parmN是形参列表中最后一个形参名的标识符 |
| void va_copy(va_list dest, va_list src) | 该宏把dest初始化为src当前状态的备份(C99) |
| type va_arg(va_list ap, type) | 该宏展开为一个表达式,其值和类型都与ap表示的形参列表的下一项相同,type是该项的类型。每次调用该宏都前进到ap中的下一项 |
| void va_end(va_list ap) | 该宏关闭以上过程,可能导致ap在再次调用va_start()之前不可用 |
| void va_copy(va_list dest, va_list src) | 该宏把dest初始化为src当前状态的备份(C99) |
变参函数比使用变参宏更复杂,但是函数的应用范围更广。
示例:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
double sum(int, ...);
int main(int argc, char* argv[])
{
double s, t;
s = sum(3, 1.1, 2.5, 13.3);
t = sum(6, 1.1, 2.1, 13.1, 4.1, 5.1, 6.1);
printf("return value for "
"sum(3, 1.1, 2.5, 13.3): %g\n", s);
printf("return value for "
"sum(6, 1.1, 2.1, 13.1, 4.1, 5.1, 6.1): %g\n", t);
system("pause");
return 0;
}
double sum(int lim, ...)
{
va_list ap; // 声明一个对象储存参数
//va_list apcopy;
double tot = 0;
int i;
va_start(ap, lim); // 把ap初始化为参数列表
//va_arg()不提供退回之前参数的方法,所以有必要保存va_list类型变量的副本
//va_copy(apcopy, ap);
for (i = 0; i < lim; i++)
{
tot += va_arg(ap, double); // 访问参数列表中的每一项
}
va_end(ap); // 清理工作
//调用了va_end(ap)后,只有用va_start(ap, lim)重新初始化ap后,才能使用变量ap
return tot;
}
运行测试