C语言可变参

    xiaoxiao2021-03-25  85

    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 <stdio.h>; #include <string.h>; /*********************************************************************/ //#include <stdarg.h>;//使用下面五行代码就可以不用头文件(只适用于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; }
    转载请注明原文地址: https://ju.6miu.com/read-23845.html

    最新回复(0)