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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4339412/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 07:16:49  来源:igfitidea点击:

How to use __VA_ARGS__ inside a C function instead of macro?

c

提问by Jona

Possible Duplicate:
C/C++: Passing variable number of arguments around

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

I'm currently using the following macro declared on my C file.

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

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

Now that call works just fine, but turns out that I need to be able to create a C function that looks something like this:

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

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

So that function doesn't work, I get an error

所以该功能不起作用,我收到一个错误

"Error : undefined identifier __VA_ARGS__"

“错误:未定义标识符 __VA_ARGS__”

The complexity of my project requires to have a function since it's an interface... So how can I get the parameters ... and pass them to the printf function? Or better what am I doing wrong?

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

Thanks!

谢谢!

回答by John Kugelman

Each of the ?printffunctions has a corresponding v?printffunction which does the same thing but takes a va_list, a variable argument list.

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

Side note:Notice that va_starttakes the name of the last argument before the ...as a parameter. va_startis a macro which does some stack-based magic to retrieve the variable arguments and it needs the address of the last fixed argument to do this.

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

As a consequence of this, there has to be at least one fixed argument so you can pass it to va_start. This is why I added the formatargument instead of sticking with the simpler COMMON_Print(...)declaration.

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

See:http://www.cplusplus.com/reference/clibrary/cstdio/vprintf/

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

回答by Michael Mrozek

__VA_ARGS__is only for macros; variadic functions are rather different. You need to use va_start, va_argand va_endfrom stdarg.hto handle them.

__VA_ARGS__仅适用于宏;可变参数函数相当不同。您需要使用va_start,va_argva_endfromstdarg.h来处理它们。

First, your function needs at least one named parameter, e.g.:

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

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

Then you can define a va_listand use va_startto set it:

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

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

Now you can use argsto access the arguments; calling va_arg(args, TYPE)will return the next variadic argument, so you can just keep calling that until you've read all the arguments.

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

If you're just trying to call printf, there's a printf variant called vprintfthat takes the va_listdirectly:

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

vprintf(fmt, args);

There is no easy way to call one variadic function from another; you need something like vprintfthat takes the whole va_list

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

回答by nos

__VA_ARGS__is for macros only.

__VA_ARGS__仅适用于宏。

Chaining the variable number of argument to another function can't be done directly. Instead you have to pass a va_list , and the function you're calling have to take a va_list. Luckily there's a variation of printf that does this, your function have to be written this way:

不能直接将可变数量的参数链接到另一个函数。相反,您必须传递 va_list ,并且您调用的函数必须采用 va_list。幸运的是, printf 有一个变体可以做到这一点,你的函数必须这样写:

void COMMON_Print(char *format,...)
{    
  va_list args;
  va_begin(args,format);
  vsprintf(format,args);
  va_end(args);
}

回答by Dima

What you are looking for is the Ellipsisoperator.

您正在寻找的是省略号运算符。