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

时间:2010-12-02 20:16:20

标签: c

  

可能重复:
  C/C++: Passing variable number of arguments around

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

#define COMMON_Print(...) printf (__VA_ARGS__)

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

void COMMON_Print(...)
{    
    printf (__VA_ARGS__);
}

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

  

“错误:未定义标识符__VA_ARGS __”

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

谢谢!

4 个答案:

答案 0 :(得分:43)

每个?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);
}

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

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

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

答案 1 :(得分:19)

__VA_ARGS__仅适用于宏;可变函数是相当不同的。您需要使用va_arg中的va_startva_endstdarg.h来处理它们。

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

void COMMON_Print(const char* fmt, ...)

然后,您可以定义va_list并使用va_start进行设置:

va_list args;
va_start(args, fmt);
// your code here
va_end(args);

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

如果您只是想致电printf,则会有一个名为vprintf的printf变体直接接收va_list

vprintf(fmt, args);

没有简单的方法可以从另一个中调用一个可变参数函数;你需要vprintf之类的东西,它需要整个va_list

答案 2 :(得分: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);
}

答案 3 :(得分:3)

您正在寻找的是Ellipsis运营商。