给出以下示例代码:
#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个函数不仅没有参数,而且具有空返回类型-这导致了我的问题,而与宏无关。
答案 0 :(得分:1)
调用宏时,其参数列表中最后一个命名参数之后的所有标记(此宏不包含任何标记)(包括逗号)都将成为变量参数。此令牌序列会替换宏正文中出现的标识符
__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)以便可以有条件添加逗号的原因。