傳遞可變數量的參數

假設我有一個帶有可變數量參數的C函數:如何調用另外一個函數,該函數須要從其內部獲取可變數量的參數,並將全部參數傳遞到第一個函數中? less

例: 函數

void format_string(char *fmt, ...);

void debug_print(int dbg_lvl, char *fmt, ...) {
    format_string(fmt, /* how do I pass all the arguments from '...'? */);
    fprintf(stdout, fmt);
 }

#1樓

羅斯的解決方案有點清理乾淨了。 僅當全部args都是指針時纔有效。 若是__VA_ARGS__爲空(Visual Studio C ++和GCC都這樣作),語言實現也​​必須支持__VA_ARGS__之前的逗號。 spa

// pass number of arguments version
 #define callVardicMethodSafely(...) {value_t *args[] = {NULL, __VA_ARGS__}; _actualFunction(args+1,sizeof(args) / sizeof(*args) - 1);}


// NULL terminated array version
 #define callVardicMethodSafely(...) {value_t *args[] = {NULL, __VA_ARGS__, NULL}; _actualFunction(args+1);}

#2樓

我不肯定這是否適用於全部編譯器,但它對我來講已經有用了。 debug

void inner_func(int &i)
{
  va_list vars;
  va_start(vars, i);
  int j = va_arg(vars);
  va_end(vars); // Generally useless, but should be included.
}

void func(int i, ...)
{
  inner_func(i);
}

若是須要,能夠將...添加到inner_func(),但不須要它。 它起做用,由於va_start使用給定變量的地址做爲起點。 在這種狀況下,咱們在func()中給它一個變量的引用。 因此它使用該地址並在堆棧以後讀取變量。 inner_func()函數從func()的堆棧地址讀取。 所以,只有兩個函數使用相同的堆棧段時纔有效。 指針

若是你給它們任何var做爲起點,那麼va_start和va_arg宏一般會起做用。 所以,若是您但願您能夠將指針傳遞給其餘函數並使用它們。 您能夠輕鬆製做本身的宏。 全部的宏都是類型轉換內存地址。 然而,使它們適用於全部編譯器和調用約定是使人討厭的。 所以,使用編譯器附帶的內容一般更容易。 code


#3樓

要傳遞省略號,您必須將它們轉換爲va_list並在第二個函數中使用該va_list。 特別; orm

void format_string(char *fmt,va_list argptr, char *formatted_string);


void debug_print(int dbg_lvl, char *fmt, ...) 
{    
 char formatted_string[MAX_FMT_SIZE];

 va_list argptr;
 va_start(argptr,fmt);
 format_string(fmt, argptr, formatted_string);
 va_end(argptr);
 fprintf(stdout, "%s",formatted_string);
}

#4樓

沒有辦法調用(例如)printf而不知道你傳遞了多少個參數,除非你想進入頑皮和非便攜的技巧。 內存

一般使用的解決方案是始終提供另外一種形式的vararg函數,所以printf具備vprintf ,它使用va_list代替... ...版本只是va_list版本的包裝器。 編譯器


#5樓

你也能夠嘗試宏。 string

#define NONE    0x00
#define DBG     0x1F
#define INFO    0x0F
#define ERR     0x07
#define EMR     0x03
#define CRIT    0x01

#define DEBUG_LEVEL ERR

#define WHERESTR "[FILE : %s, FUNC : %s, LINE : %d]: "
#define WHEREARG __FILE__,__func__,__LINE__
#define DEBUG(...)  fprintf(stderr, __VA_ARGS__)
#define DEBUG_PRINT(X, _fmt, ...)  if((DEBUG_LEVEL & X) == X) \
                                      DEBUG(WHERESTR _fmt, WHEREARG,__VA_ARGS__)

int main()
{
    int x=10;
    DEBUG_PRINT(DBG, "i am x %d\n", x);
    return 0;
}
相關文章
相關標籤/搜索