将 va_list 传递给其他函数

Passing va_list to other functions

我一直在尝试将可变参数传递给 C 中的其他函数,但它在不同的运行时环境中以及在同一环境中的不同运行中产生不一致的结果:

int main() 
{ 
    int result = myprintf("Something \n %d", 9); 
    return result;
}

int myprintf(const char *format, ...){
    printf("Something \n %d", 9); 
    printf("\n");
    va_list args;        
    va_start(args, format);    
    int result = printf(format,args);
    printf("\n");
    va_end(args);
    return result;
} 

产生的结果是:

WWW.FIRMCODES.COM 
 9
WWW.FIRMCODES.COM 
 438656664

我找不到“438656664”的原因。

您不能将可变参数传递给可变参数函数。相反,您必须调用一个以 va_list 作为参数的函数。标准库提供了 printfscanf 的变体,它们采用 va_list;他们的名字有前缀 v.

您的示例应如下所示:

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

int printfln(const char *format, ...)
{
    int result;
    va_list args;

    va_start(args, format);
    result = vprintf(format, args);
    printf("\n");
    va_end(args);

    return result;
}

int main()
{
    int result = printfln("Something \n %d", 9);

    printf("(%d)\n", result);

    return 0;
}

有一些陷阱,例如,当你想调用两个 v... 函数来打印到屏幕和一个日志文件时:v... 函数可能会耗尽 va_list,所以如果你的代码应该是可移植的,你必须在每次调用中传递一个新的。

或者,您可以简单地使用包装器宏:

#include <stdio.h>

#define myprintf(fmt, ...) ( printf("Something \n %d\n", 9), printf(fmt, __VA_ARGS__) )

int main (void) 
{ 
    int result = myprintf("Something \n %d\n", 9); 
    printf("%d\n", result);
}

请注意使用逗号运算符来保留对调用方的右侧 printf 调用的返回值。

这不亚于(同样危险的)stdarg.h 可变参数函数。

对于 C++ 研究员也正在阅读此内容。实际上,您可以在不使用 vprintf 的情况下使用包扩展来完成。 当您需要包装一个采用省略号 (...) 而不是 va_list.

例如:

template <class ... Args>
void foo(const char *format, Args ... args)
{
    printf(format, args...);
}

这里class...args是模板参数包,args...args是函数参数包,args...是函数参数包扩展