C语言可变参

C语言可变参

必需掌握的1个自定义类型和3个宏函数

<一种自定义类型> va_list
用来定义,存放““可变参数列表”的地址”的变量
原型:
    typedef char * va_list;
<宏函数> va_start(va_list 表指针,最后一个“确定参数”)
将表头地址赋值给表指针
原型:
    #define _INTSIZEOF(n) ((sizeof(n)+sizeof(int)-1)&~(sizeof(int) - 1) )
    #define va_start(ap,v) ( ap = (va_list)&v + _INTSIZEOF(v) )
<宏函数> va_arg(va_list 表指针,参数类型)
根据表指针和参数类型,依次返回数据(表指针每次调用,自动完成自偏移)
原型:
    #define va_arg(ap,t) ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )
<宏函数> va_end(va_list 表指针)
将表指针赋值为NULL
原型:
    #define va_end(ap) ( ap = (va_list)0 )
备注
上面的原型来自于(X86 VC)stdarg.h中。
由于1)硬件平台的不同2)编译器的不同,所以定义的宏也有所不同,仅供参考。
从内存角度分析
C语言的函数是从右向左的顺序入栈的,如下图所示是x86的
(这是x86的,ARM和这个相反,是从左向右)
高地址  |-----------------------------|
        |函数返回地址                  |
        |-----------------------------|
        |.............................|
        |-----------------------------|<--va_arg后ap指向
        |第n个参数(第一个可变参数)      |
        |-----------------------------|<--va_start后ap指向
        |第n-1个参数(最后一个固定参数)  |<-- &v
        |.............................|
        |第1个参数(第一个固定参数)      |
低地址  |-----------------------------|

例子

#include ;
#include ;
/*********************************************************************/
//#include ;//使用下面五行代码就可以不用头文件(只适用于x86)

typedef char * va_list;

#define _INTSIZEOF(n) ((sizeof(n)+sizeof(int)-1)&~(sizeof(int) - 1) )

#define va_start(ap,v) ( ap = (va_list)&v + _INTSIZEOF(v) )

#define va_arg(ap,t) ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )

#define va_end(ap) ( ap = (va_list)0 )
/*********************************************************************/

/* ANSI标准形式的声明方式,括号内的省略号表示可选参数 */
int demo(char *msg, ... )
{
    va_list argp;                   /* 定义保存函数参数的结构 */
    int argno = 0;                  /* 纪录参数个数 */
    char *para;                     /* 存放取出的字符串参数 */

    /* argp指向传入的第一个可选参数,msg是最后一个确定的参数 */
    va_start( argp, msg );

    while (1)
    {
        para = va_arg( argp, char *);  /*取出当前的参数,类型为char *. */
        if ( strcmp( para, "\0") == 0 )/* 采用空串指示参数输入结束 */
            break;
        printf("Parameter #%d is: %s \n", argno, para);
        argno++;
    }
    va_end( argp ); /* 将argp置为NULL */
    return 0;
}

int main( void )
{
    demo("DEMO", "This", "is", "a", "demo!" ,"333333", "\0");
    return 0;
}

你可能感兴趣的:(C语言)