#include <stdarg.h>
va_list ap;
void va_start(va_list ap, last);
type va_arg(va_list ap, type);
void va_end(va_list ap);
void va_copy(va_list dest, va_list src);
va_list ap:声明可变参数指针
va_start:初始化ap,使其指向参数last的后一个可变参数
Each invocation of va_start() must be matched by a corresponding invocation of va_end() in the
same function // 同一函数内每一个va_start必须配有一个对应的va_end
va_arg:将ap指向的参数转换为type类型返回,同时ap后移,指向下一个可变参数
va_end: 结束ap(ap一般赋值为NULL,ap变为无定义值,va_end可能伴随内存释放,见下边va_copy)
va_copy: src复制给dest
An obvious implementation would have a va_list be a pointer to the stack frame of the variadic
function. In such a setup (by far the most common) there seems nothing against an assignment
va_list aq = ap;
Unfortunately, there are also systems that make it an array of pointers (of length 1), and
there one needs
va_list aq;
*aq = *ap;
Each invocation of va_copy() must be matched by a corresponding invocation of va_end() in the
same function // 同一函数内每一个va_copy必须配有一个对应的va_end
陷阱:
va_arg宏的第2个参数不能被指定为char、short或者float类型。
因为char和short类型的参数会被转换为int类型,而float类型的参数会被转换为double类型
在C语言中,调用一个不带原型声明的函数时,调用者会对每个参数执行“默认实际参数提升(default argument promotions)”。该规则同样适用于可变参数函数——对可变长参数列表超出最后一个有类型声明的形式参数之后的每一个实际参数,也将执行上述提升工作。
然后,调用者将提升后的参数传递给被调用者。
所以,可变参函数内是绝对无法接收到上述类型的实际参数的。
c = va_arg(ap,char); // error
因为我们无法传递一个char类型参数,如果传递了,它将会被自动转化为int类型。上面的式子应该写成:
c = va_arg(ap,int); // right
#include <stdio.h>
#include <stdarg.h>
int pp(char a, ...)
{
va_list p, q;
double n;
va_start(p, a);
while (1) {
double n;
n = va_arg(p, double);
if (n <= 0) break;
printf("%f\n", n);
}
va_end(p); // va_start(p...)
va_start(p, a);
n = va_arg(p, double);
printf("%f\n", n);
va_copy(q, p);
n = va_arg(q, double);
printf("%f\n", n);
va_end(q); // va_start(q...)
va_end(p); // va_start(p...)
return 0;
}
int main()
{
pp('a', 1.0, 2.0, 3.0, 4.0, 5.0, -1.0);
return 0;
}
输出:
root@ubuntu:~/wdc/progams/vaargs# ./varg
1.000000
2.000000
3.000000
4.000000
5.000000
1.000000
2.000000
root@ubuntu:~/wdc/progams/vaargs#