作用:
可变参数的操作
概要:
#include <stdarg.h>
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对象,这个对象可用va_start(),va_arg(),va_end()这三个宏来操作。
参数last是参数列表中的第一个参数,这个参数类型已知。
因为last遍历可能被用在va_start()中,因此不能定义为register变量、函数或者是一个数组类型。
va_copy()
系统会复制来的参数保存到一个指针数组中
上述赋值也可写成:
每次调用完va_copy()后,必须在同一函数中调用va_end()。某些系统中可能不支持va_copy(),可用 __va_copy()替代。
特征:
va_start(), va_arg(), va_end(), and va_copy() 宏是线程安全的(thread-safe)
注:
The va_start(), va_arg(), 和va_end() 确定于C89。C99定义了宏va_copy()
在某些系统中,va_end包含一个关闭符号“}”,匹配与va_start()的开始符号“{”.因此这两个函数必须成对出现在一个函数中
示例:
可变参数的操作
概要:
#include <stdarg.h>
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);
描述:
函数的参数可能会是不同类型的可变参数。头文件<stdarg.h>中声明了va_list及定义了三个宏定义,用于遍历被调函数中未知的参数个数及类型。
调用该可变参数必须先声明一个va_list对象,这个对象可用va_start(),va_arg(),va_end()这三个宏来操作。
va_start()
参数last是参数列表中的第一个参数,这个参数类型已知。
因为last遍历可能被用在va_start()中,因此不能定义为register变量、函数或者是一个数组类型。
va_arg()
va_arg()展开后有下一个参数的类型和值。参数ap是va_list中的参数,由va_start()初始化。每次调用va_arg()都会修改ap的值,即将ap移动到下一个参数处。参数type必须是指定的参数,可以是指针类型。
如果没有下一个参数了,或者实际类型跟参数type不匹配,将会发生随机错误。
经测试,type类型不能是char或者short类型!
如果使用va_arg(ap,type)将ap传到另一个函数,那么在返回该函数后ap将被释放。va_end()
每次调用va_end()时,必须要在同一函数先调用与之相对的va_end()。调用va_end(ap)后,ap将变成未定义。多个遍历列表中,成对出现va_start()和va_end()是可能的,va_end()可能是一个宏或者是一个函数。va_copy()
宏va_copy()可以从源参数列表中复制参数值到已初始化的变量中。
va_list aq = ap;
系统会复制来的参数保存到一个指针数组中
va_list aq;
*aq = *ap;
上述赋值也可写成:
va_list aq;
va_copy(aq, ap);
...
va_end(aq);
每次调用完va_copy()后,必须在同一函数中调用va_end()。某些系统中可能不支持va_copy(),可用 __va_copy()替代。
特征:
va_start(), va_arg(), va_end(), and va_copy() 宏是线程安全的(thread-safe)
注:
The va_start(), va_arg(), 和va_end() 确定于C89。C99定义了宏va_copy()
注2:
这些宏不兼容历史版本。历史版本可在<varargs.h>中找到。
先前的版本配置如下:
#include <varargs.h>
void
foo(va_alist)
va_dcl
{
va_list ap;
va_start(ap);
while (...) {
...
x = va_arg(ap, type);
...
}
va_end(ap);
}
在某些系统中,va_end包含一个关闭符号“}”,匹配与va_start()的开始符号“{”.因此这两个函数必须成对出现在一个函数中
BUGS
不像varargs宏,宏stdarg不允许写一个不匹配的参数的函数。即当将varargs代码转换为stdarg代码就会出问题
示例:
#include <stdio.h>
#include <stdarg.h>
void foo(char *fmt, ...)
{
va_list ap;
int d;
char c, *s;
va_start(ap, fmt);
while (*fmt)
switch (*fmt++) {
case 's': /* string */
s = va_arg(ap, char *);
printf("string %s\n", s);
break;
case 'd': /* int */
d = va_arg(ap, int);
printf("int %d\n", d);
break;
case 'c': /* char */
/* need a cast here since va_arg only
takes fully promoted types */
c = (char) va_arg(ap, int);
printf("char %c\n", c);
break;
}
va_end(ap);
}
该头文件的最新版本,可参见http://www.kernel.org/doc/man-pages/
以上内容翻译自debian 8系统中man va_arg命令