假设我有一个C函数,它有一个可变数量的参数:我如何调用另一个函数,它期望从它内部有一个可变数量的参数,传递进入第一个函数的所有参数?
例子:
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);
}
我不确定这是否适用于所有编译器,但到目前为止对我来说是有效的。
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()的堆栈地址中读取。因此,只有当两个函数使用相同的堆栈段时,它才有效。
如果你给va_start和va_arg宏一个变量作为起始点,它们通常会工作。如果你愿意,你也可以把指针传递给其他函数。您可以很容易地创建自己的宏。宏所做的就是对内存地址进行类型转换。然而,让它们适用于所有编译器和调用约定是很烦人的。所以使用编译器自带的通常更容易。
为了传递省略号,像往常一样初始化一个va_list,然后简单地将它传递给第二个函数。你不使用va_arg()。特别地;
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);
}
可以对函数调用使用内联汇编。(在这段代码中,我假设参数是字符)。
void format_string(char *fmt, ...);
void debug_print(int dbg_level, int numOfArgs, char *fmt, ...)
{
va_list argumentsToPass;
va_start(argumentsToPass, fmt);
char *list = new char[numOfArgs];
for(int n = 0; n < numOfArgs; n++)
list[n] = va_arg(argumentsToPass, char);
va_end(argumentsToPass);
for(int n = numOfArgs - 1; n >= 0; n--)
{
char next;
next = list[n];
__asm push next;
}
__asm push fmt;
__asm call format_string;
fprintf(stdout, fmt);
}