假设我有一个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);
 }

当前回答

为了传递省略号,像往常一样初始化一个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 func(type* values) {
        while(*values) {
            x = *values++;
            /* do whatever with x */
        }
    }

func((type[]){val1,val2,val3,val4,0});

为了传递省略号,像往常一样初始化一个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);
}

虽然你可以通过先将它存储在本地缓冲区来解决传递格式化器的问题,但这需要堆栈,有时可能会成为处理问题。我试着跟着做,看起来效果不错。

#include <stdarg.h>
#include <stdio.h>

void print(char const* fmt, ...)
{
    va_list arg;
    va_start(arg, fmt);
    vprintf(fmt, arg);
    va_end(arg);
}

void printFormatted(char const* fmt, va_list arg)
{
    vprintf(fmt, arg);
}

void showLog(int mdl, char const* type, ...)
{
    print("\nMDL: %d, TYPE: %s", mdl, type);

    va_list arg;
    va_start(arg, type);
    char const* fmt = va_arg(arg, char const*);
    printFormatted(fmt, arg);
    va_end(arg);
}

int main() 
{
    int x = 3, y = 6;
    showLog(1, "INF, ", "Value = %d, %d Looks Good! %s", x, y, "Infact Awesome!!");
    showLog(1, "ERR");
}

希望这能有所帮助。

罗斯的解决方案清理了一点。只有当所有参数都是指针时才有效。此外,如果__VA_ARGS__为空,语言实现必须支持省略前面的逗号(Visual Studio c++和GCC都支持)。

// 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);}

在不知道传递给printf的参数有多少的情况下调用printf是不可能的,除非您想要使用一些淘气且不可移植的技巧。

通常使用的解决方案是始终提供另一种形式的vararg函数,因此printf有vprintf,它采用va_list代替....…版本只是va_list版本的包装。