C库中对函数的可变参数的支持

来源:互联网 发布:windows移动中心在哪 编辑:程序博客网 时间:2024/05/20 20:43
C语言在<stdarg.h> 头文件定义了一些宏,当函数参数未知时去获取函数的参数。
包括一个va_list类型和三个函数(宏)va_start, va_arg和va_end .
变量和定义
va_list类型通过stdarg宏定义来访问一个函数的参数表,参数列表的末尾会用省略号省略

声明:void va_start(va_list ap, last_arg);
用va_arg和va_end宏初始化参数ap,last_arg是传给函数的固定参数的最后一个,省略号之前的那个参数注意va_start必须在使用va_arg和va_end之前调用

声明:type va_arg(va_list ap, type);

用type类型扩展到参数表的下个参数
注意ap必须用va_start初始化,如果没有下一个参数,结果会是undefined

声明:void va_end(va_list ap); 允许一个有参数表(使用va_start宏)的函数返回,如果返回之前没有调用va_end,结果会是undefined。参数变量列表可能不再使用(在没调用va_start的情况下调用va_end) 

windows下的定义如下:
复制代码
 #ifndef _VA_LIST_DEFINED  
    #ifdef  _M_ALPHA  
    typedef struct {  
            char *a0;       /* pointer to first homed integer argument */  
            int offset;     /* byte offset of next parameter */  
    } va_list;  
    #else  
    typedef char *  va_list;  
    #endif  
    #define _VA_LIST_DEFINED  
    #endif  
      
    #ifdef  _M_IX86       
      
    #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 )  
      
    #elif   defined(_M_MRX000) 
复制代码
   
其中比较不容易理解的就是_INTSIZEOF宏:其实_INTSIZEOF(n)表示得到变量n的内存大小,这里要考虑内存对齐问题,在32位中系统中,一般是4字节(32位)对齐。(sizeof(n) + sizeof(int))表示凑成4字节的整数被,(sizeof(n) + sizeof(int)) & (sizeof(int) -1)表示将凑齐后多余的字节删除。比如说10字节的变量,占内存的大小为:(10+4)&((11111100)2)= 12字节;

C语言中利用可变参数的函数就是最常用的printf。而且C标准库中也是包括3个参数含有va_list的函数:vprintf,vfprintf,vsprintf。而这三个函数与对应的不加“v“的函数用法是一样的,只不过,vprintf类要求可变参数用va_list指定。其实printf就是利用vprintf来实现的。

下面是一个模仿printf的函数:
复制代码
#include <stdio.h>
 #include <stdarg.h>
 void print(char* fmt,...){
     va_list ap;
     int d;
     char c,*s;
     double f;
     va_start(ap, fmt);
     while(*fmt)
         switch(*fmt++){
             case 's':
                 s=va_arg(ap,char*);
                 printf("string: %s\n",s);
                 break;
             case 'd':
                 d=va_arg(ap,int);
                 printf("int: %d\n",d);
                 break;
             case 'c':
                 c=(char)va_arg(ap,int);
                 printf("char: %c\n",c);
                 break;
             case 'f':
                 f=va_arg(ap,double);
                 printf("double: %f\n",f);
                 break;
         }
     va_end(ap);
 }
 int main(){
     char* s="hello world";
     char c='H';
     int d=333;
     double f=79.998;
     print("%s %d %c %f",s,d,c,f);
 }
复制代码
0 0
原创粉丝点击