Technorati 标签: va_list, va_start, va_arg, va_end

这个的使用还是非常简单的,还是先以man的一个例子说明:

#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':
                /* need a cast here since va_arg only takes fully promoted types  *///注释是照抄的,发现去掉(char)强传后没有影响,为什么?
                c = (char)va_arg(ap, int);
                printf("char %c\n", c);
                break;
        }

    va_end(ap);
}

int main()
{
    foo("sdccds", "Hello", 1, 'w', 'w', 2, "World!");

    return 0;
}

输出:

y@y-VirtualBox:~/Training$ ./test
string Hello
int 1
char w
char w
int 2
string World!
函数原型:

#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:类型,ap即argument pointer

va_start:初始化ap,第二个变量必须是…之前的变量名

va_arg:在使用va_start(last, ap)初始化之后,第一次调用va_arg,它会返回last之后的变长参数表中的第一个参数,并修改ap指向下一个参数;接下来每调用一次va_arg都会返回返回一个参数,有将ap向前移动一步。va_arg除了需要ap这个参数指针之外,还需要一个数据类型type,用来决定一步应该迈多大。

va_end:与va_start对应

va_copy是用来复制va_list的,没有用到,在此就不乱讲了,免得弄错,有懂的读者可以告诉我~~

注意:

在使用过程中必须设定变长参数表解析的结束条件,可变参数并没有想象的那么智能,不能实现所有参数的类型和数目都自动判断。因此,使用时,多数会通过数值或者条件让程序知道参数的数目。例如,上面例子中的while (*fmt)就是结束条件,下面再举一个以数值边界作为条件的例子。