C语言变参宏和可变参数函数
变参宏:...
和 __VA_ARGS__
#define PR(...) printf(__VA_ARGS__);
注意:省略号只能代替最后的宏参数
#define WRONG(X, ..., Y) #X #__VA_ARGS__ #Y // 不能这样做
可变参数:stdarg.h
stdarg.h
为函数提供了可变参数的功能。但是用法比较复杂。必须按照如下步骤进行:
提供一个使用省略号的函数原型;
在函数定义中创建一个
va_list
类型的变量;用宏把该变量初始化为一个参数列表;
用宏访问参数列表;
用宏完成清理工作。
这种函数的原型应该有一个形参列表,其中至少有一个形参和一个省略号,省略号必须放在最后。
声明在 stdarg.h
中的 va_list
类型代表一种用于储存形参列表中省略号部分的数据对象。
#include <stdio.h>
#include <stdarg.h>
double sum(int lim, ...)
{
va_list ap; // 声明一个对象存储参数
double tot = 0;
va_start(ap, lim); // 把ap初始化为参数列表
for(int i = 0; i < lim; ++i)
tot += va_arg(ap, double); // 访问参数列表中的每一项
va_end(ap); // 清理工作
return tot;
}
int main()
{
printf("%lf\n", sum(3, 1.1, 2.2, 3.3));
return 0;
}
注意:传入的实参类型必须与宏参数的类型相匹配。如果第一个参数是
10.0
,va_arg(ap, double)
可以正常工作。但是如果参数是10
,此代码可能会出错。这里不会像赋值那样把int
类型自动转换成double
类型。
注意:
va_start()
宏的第 2 个参数必须是...
前第 1 个形参,用以标记可变参数的位置。
最后,要使用 va_end()
宏完成清理工作。例如,释放动态分配用于存储参数的内容。该宏接受一个 va_list
类型的变量。
调用 va_end(ap)
之后,只有用 va_start
重新初始化 ap
后,才能使用变量 ap
。
因为 va_arg()
不提供退回之前参数的方法,所以有必要保存 va_list
类型变量的副本。C99 新增了一个宏用于处理这种情况:va_copy()
。该宏接受两个 va_list
类型的变量作为参数,它把第 2 个参数拷贝给第 1 个参数:
va_list ap;
va_iist apcopy;
double tic;
int toc;
// ...
va_start(ap, lim); // 把ap初始化为一个参数列表
va_copy(apcopy, ap); // 把apcopy作为ap的副本
tic = va_arg(ap, double); // 检索第1个参数
toc = va_arg(ap, int); // 检索第2个参数
此时,即使删除了 ap
,也可以从 apcopy
中检索两个参数。
版权声明:
本站所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自
个人技术心得!
喜欢就支持一下吧