2012-08-10 42 views
3

考虑宏扩展后重新扫描'defined'操作符:它应该工作吗?

#define FOOBAR (defined(FOO) || defined(BAR)) 

#if FOOBAR 
/* Do stuff. */ 
#endif 

如若这项工作?我在问,因为显然我的编译器没有问题,但doxygen内部预处理器认为#if存在语法错误。我知道我可以解决这个问题

#if defined(FOO) || defined(BAR) 
#define FOOBAR 1 
#endif 
#if FOOBAR 
/* Do stuff. */ 
#endif 

回答

4

从C99规格:

6.10.1.3

之前评价,在预处理标记的列表中,将成为宏调用 的控制常量表达式被替换(除了那些宏名称由定义的一元运算符修改为 ),就像在普通文本中一样。如果定义的令牌为 作为此替换过程的结果生成或使用定义的一元运算符 与宏替换之前的两个指定表单中的一个不匹配,则行为为 未定义。

因此,如果您使用的宏如您所做的那样扩展到defined,那么结果是未定义的。

与C规范中大多数未定义的东西一样,它的未定义因为标准之前的实现以不同的方式处理它。

+0

+1,...或者委员会认为编译器实现者承担了GCC预处理器手册中特定错误条件 – 2012-08-10 19:50:26

+0

的负担太多:'如果定义的操作符由于宏扩展而出现, C标准说行为是不确定的。 GNU cpp将它视为一个真正定义的运算符,并对其进行正常评估。如果您使用命令行选项“-pedantic”,它会警告您的代码在哪里使用此功能,因为其他编译器可能会以不同方式处理它。 – Johanness 2012-12-30 11:30:45

0

这听起来像一个特定于编译器的问题。只要你只是使用这个编译器,就试试看 - 在/*do stuff*/部分放一些代码,看看代码是否被编译。

+1

我不是一个真正的推论“它是如何工作的”,而是“它与我的特定编译器是如何工作的”。这将构成*实验编程*,我认为这不是一个好的工程。由于C和预处理器行为是在国际标准中规定的,所以我们应该在这里寻找*明确*答案。 – Jens 2012-08-11 07:34:26