zoukankan      html  css  js  c++  java
  • va_list 、va_start、 va_arg、 va_end 使用说明【转】

    转自:https://blog.csdn.net/f110300641/article/details/83822290

    在ANSI C中,这些宏的定义位于stdarg.h中:

    typedef char *va_list;

    va_start宏,获取可变参数列表的第一个参数的地址(list是类型为va_list的指针,param1是可变参数最左边的参数):

    #define va_start(list,param1)   ( list = (va_list)&param1+ sizeof(param1) )

    va_arg宏,获取可变参数的当前参数,返回指定类型并将指针指向下一参数(mode参数描述了当前参数的类型):

    #define va_arg(list,mode)   ( (mode *) ( list += sizeof(mode) ) )[-1]

    va_end宏,清空va_list可变参数列表:

    #define va_end(list) ( list = (va_list)0 )

    注:以上sizeof()只是为了说明工作原理,实际实现中,增加的字节数需保证为为int的整数倍

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

    为了理解这些宏的作用,我们必须先搞清楚:C语言中函数参数的内存布局。首先,函数参数是存储在栈中的,函数参数从右往左依次入栈。

    以下面函数为讨论对象:

    void test(char *para1,char *param2,char *param3, char *param4) { va_list list; ...... return; }

    在linux中,栈由高地址往低地址生长,调用test函数时,其参数入栈情况如下:

     当调用va_start(list,param1) 时:list指针指向情况对应下图:

    最复杂的宏是va_arg。

    1.  
      #include <stdio.h>
    2.  
      #include <stdarg.h>
    3.  
       
    4.  
      void var_test(char *format, ...)
    5.  
      {
    6.  
      va_list list;
    7.  
      va_start(list,format);
    8.  
       
    9.  
      char *ch;
    10.  
      while(1)
    11.  
      {
    12.  
      ch = va_arg(list, char *);
    13.  
       
    14.  
      if(strcmp(ch,"") == 0)
    15.  
      {
    16.  
      printf(" ");
    17.  
      break;
    18.  
      }
    19.  
      printf("%s ",ch);
    20.  
      }
    21.  
      va_end(list);
    22.  
      }
    23.  
       
    24.  
      int main()
    25.  
      {
    26.  
      var_test("test","this","is","a","test","");
    27.  
      return 0;
    28.  
      }

    附:可变参数应用实例

    1.printf实现

    1.  
      #include <stdarg.h>
    2.  
       
    3.  
      int printf(char *format, ...)
    4.  
      {
    5.  
      va_list ap;
    6.  
      int n;
    7.  
       
    8.  
      va_start(ap, format);
    9.  
      n = vprintf(format, ap);
    10.  
      va_end(ap);
    11.  
      return n;
    12.  
      }

    2.定制错误打印函数error

    1.  
      #include <stdio.h>
    2.  
      #include <stdarg.h>
    3.  
       
    4.  
      void error(char *format, ...)
    5.  
      {
    6.  
      va_list ap;
    7.  
      va_start(ap, format);
    8.  
      fprintf(stderr, "Error: ");
    9.  
      vfprintf(stderr, format, ap);
    10.  
      va_end(ap);
    11.  
      fprintf(stderr, " ");
    12.  
      return;
    13.  
  • 相关阅读:
    VS2015预览版中的C#6.0 新功能(一)
    REST总结
    MVC和传统的以模板为中心的web架构比较
    实现两个select list box间item的移动和过滤
    异步编程
    简述System.Windows.Forms.Timer 与System.Timers.Timer用法区别
    C#导出EXCEL,并生成charts表
    CRC16位校验
    c# 后台GET、POST、PUT、DELETE传输发送json数据
    UDP通讯
  • 原文地址:https://www.cnblogs.com/sky-heaven/p/11602919.html
Copyright © 2011-2022 走看看