va_list 、va_start、 va_arg、 va_end 使用說明【轉】

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

在ANSI C中,這些宏的定義位於stdarg.h中:函數

typedef char *va_list;佈局

va_start宏,獲取可變參數列表的第一個參數的地址(list是類型爲va_list的指針,param1是可變參數最左邊的參數):ui

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

va_arg宏,獲取可變參數的當前參數,返回指定類型並將指針指向下一參數(mode參數描述了當前參數的類型):spa

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

va_end宏,清空va_list可變參數列表:3d

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

注:以上sizeof()只是爲了說明工做原理,實際實現中,增長的字節數需保證爲爲int的整數倍code

如:#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("\n");
  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, "\n");
  12.  
    return;
相關文章
相關標籤/搜索