传递可变数量的参数

假设我有一个带有可变数量参数的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;
}
相关文章
相关标签/搜索