如何在C函数中使用__VA_ARGS__而不是宏?

Jon*_*ona 25 c

可能重复:
C/C++:传递可变数量的参数

我目前正在使用我的C文件中声明的以下宏.

#define COMMON_Print(...) printf (__VA_ARGS__)
Run Code Online (Sandbox Code Playgroud)

现在该调用工作得很好,但事实证明我需要能够创建一个看起来像这样的C函数:

void COMMON_Print(...)
{    
    printf (__VA_ARGS__);
}
Run Code Online (Sandbox Code Playgroud)

因此该功能不起作用,我收到错误

"错误:未定义的标识符__VA_ARGS__"

我的项目的复杂性需要有一个函数,因为它是一个接口......那么如何获取参数...并将它们传递给printf函数?或者更好的是我做错了什么?

谢谢!

Joh*_*ica 45

每个?printf函数都有一个相应的v?printf函数,它执行相同的操作但需要va_list一个可变参数列表.

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

void COMMON_Print(char *format, ...)
{
    va_list args;

    va_start(args, format);
    vprintf(format, args);
    va_end(args);
}
Run Code Online (Sandbox Code Playgroud)

附注:请注意,va_start它将最后一个参数的名称...作为参数.va_start是一个宏,它执行一些基于堆栈的魔法来检索变量参数,它需要最后一个固定参数的地址来执行此操作.

因此,必须至少有一个固定的参数,以便您可以将其传递给va_start.这就是为什么我添加了format参数而不是坚持使用更简单的COMMON_Print(...)声明.

请参阅: http ://www.cplusplus.com/reference/clibrary/cstdio/vprintf/


Mic*_*zek 19

__VA_ARGS__仅适用于宏; 可变函数是相当不同的.您需要使用va_start,va_argva_endstdarg.h处理它们.

首先,您的函数至少需要一个命名参数,例如:

void COMMON_Print(const char* fmt, ...)
Run Code Online (Sandbox Code Playgroud)

然后你可以定义一个va_list并使用va_start它来设置它:

va_list args;
va_start(args, fmt);
// your code here
va_end(args);
Run Code Online (Sandbox Code Playgroud)

现在您可以args用来访问参数; 调用va_arg(args, TYPE)将返回下一个可变参数,所以你可以继续调用它,直到你读完所有的参数.

如果你只是想打电话printf,有一个名为printf的变种vprintf,是以va_list直接:

vprintf(fmt, args);
Run Code Online (Sandbox Code Playgroud)

没有简单的方法可以从另一个函数中调用一个可变函数; 你需要这样的东西vprintf需要整体va_list


nos*_*nos 5

__VA_ARGS__ 仅用于宏。

无法将可变数量的参数链接到另一个函数。相反,您必须传递va_list,而要调用的函数必须采用va_list。幸运的是,有一个printf可以做到这一点,您的函数必须这样写:

void COMMON_Print(char *format,...)
{    
  va_list args;
  va_begin(args,format);
  vsprintf(format,args);
  va_end(args);
}
Run Code Online (Sandbox Code Playgroud)