为什么可变参宏给我一个错误?

时间:2018-10-02 09:39:30

标签: c visual-c++ variadic-macros

给出以下示例代码:

#define vX(a, ...) ((a)(__VA_ARGS__) ? 1 : 0)

{
    int f();
    vX(f);
}

我得到error C2155: '?': invalid left operand, expected arithmetic or pointer type

另一方面,如果我向宏提供第二个参数,则它会编译fin-例如:

vX(f,1)

可以。我正在使用msvc编译器来编译C代码。

很抱歉打扰大家,但错误就在我这一边-给我带来错误的2个函数不仅没有参数,而且具有空返回类型-这导致了我的问题,而与宏无关。

2 个答案:

答案 0 :(得分:1)

来自GCC documentation

  

调用宏时,其参数列表中最后一个命名参数之后的所有标记(此宏不包含任何标记)(包括逗号)都将成为变量参数。此令牌序列会替换宏正文中出现的标识符__VA_ARGS__

因此,基本上__VA_ARGS__部分不能为空,这需要GNU扩展(__VA_OPT__)。

答案 1 :(得分:1)

关于此的预处理器规范有些冗长,但足以说明,您指定的vX必须接受至少两个参数。

原因是参数的数量很大程度上取决于宏中的逗号数量。因此,例如vX(f,)也会导致您的错误也消失。原因是我们再次提供了两个参数,即f和逗号后的空白令牌序列。

解决这个问题的一个技巧是将宏分为两个扩展:

#define vX_(a, ...) ((a)(__VA_ARGS__) ? 1 : 0)
#define vX(...) vX_(__VA_ARGS__,)

请注意我是如何添加逗号的?现在,当您编写vX(f)时,它将扩展为vX_(f,),它将再次扩展为您提供所需的表达式。虽然,在一般情况下这是行不通的,因为您会得到逗号结尾。这就是GCC引入__VA_OPT__@unwind's answer)以便可以有条件添加逗号的原因。