va_arg

- va_arg

  • 语法
#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()
  • va_start()

    • va_start()是一个宏,用来初始化va_list类型变量ap,以用于va_arg()和va_end(),必须首先被调用
    • 变量last是变量列表之前的最后一个变量,换句话说,就是函数声明时形参中已知类型中的最后一个参数,因为这个参数的地址需要在va_start()这个宏中用到,它不能是一个寄存器类型的变量,也不能是一个函数或数组类型
  • va_arg(va_list ap, type)

    • va_arg()这个宏展开表达式(有类型和 函数调用中下一个变量的 ),ap是被va_start()初始化过的变量,每一次调用va_arg()都将改变ap的值所以下次返回下一个变量的值。因为变量的类型是用格式控制符标识的,所以通过一个指针变量就能简单的获取
    • 使用va_start()宏后首次使用va_arg()宏返回last之后的变量,成功调用后返回剩余变量的值。
    • 如果后面没有变量了,或者如果变量类型和实际值的类型不匹配,会发生未知错误
    • 如果ap被传递给使用va_arg()宏的函数,那么ap的值在函数返回后变成未被定义
  • va_end()

    • 在同一个函数内每一次va_start()调用必须相应的有一个匹配的va_end()被调用,va_end()被调用后ap变成undefined,多次循环列表是允许的,va_end()可能是一个宏也可能是一个函数。

更多请参考官方文档

#include <stdio.h>
#include <stdarg.h>

void foo(char *fmt, ...)
{
    va_list ap;        //必须声明的变量
    int d;
    char c, *s;

   va_start(ap, fmt);  //初始化ap,必须首先被调用,通过fmt的地址找到参数列表,用以初始化ap
    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);
}

猜你喜欢

转载自blog.csdn.net/qq_36337149/article/details/81146649