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.  
  • 相关阅读:
    MySQL-基本sql命令
    Java for LeetCode 203 Remove Linked List Elements
    Java for LeetCode 202 Happy Number
    Java for LeetCode 201 Bitwise AND of Numbers Range
    Java for LeetCode 200 Number of Islands
    Java for LeetCode 199 Binary Tree Right Side View
    Java for LeetCode 198 House Robber
    Java for LeetCode 191 Number of 1 Bits
    Java for LeetCode 190 Reverse Bits
    Java for LeetCode 189 Rotate Array
  • 原文地址:https://www.cnblogs.com/sky-heaven/p/11602919.html
Copyright © 2011-2022 走看看