假设我有一个带有可变数量参数的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); }
罗斯的解决方案有点清理干净了。 仅当全部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);}
我不肯定这是否适用于全部编译器,但它对我来讲已经有用了。 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
要传递省略号,您必须将它们转换为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); }
没有办法调用(例如)printf而不知道你传递了多少个参数,除非你想进入顽皮和非便携的技巧。 内存
一般使用的解决方案是始终提供另外一种形式的vararg函数,所以printf
具备vprintf
,它使用va_list
代替...
...
版本只是va_list
版本的包装器。 编译器
你也能够尝试宏。 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; }