为什么要使用MACRO + 0!= 0

时间:2016-05-05 10:19:05

标签: c++ c

在我目前的代码库中,我看到以下模式:

#if SOMETHING_SUPPORTED+0 != 0
...
#endif

不幸的是,这是一个非常古老的代码库,没有人知道它是如何以及为什么开始的。我认为它是从C开始的,它慢慢地转换为C类,现在它倾向于C ++

我看不到使用先前构造而不是“经典”的明显优势,但也许我错过了一些东西:

#if SOMETHING_SUPPORTED
...
#endif

您知道为什么会使用#if MACRO+0 != 0代替#if MACRO吗?

4 个答案:

答案 0 :(得分:71)

这里的线索是代码库非常陈旧。

这个技巧可能存在,因为代码曾经被一些非常旧的预处理器移植到编译器,而预处理器中的未定义的宏在预处理器#if条件中不会被视为0。

也就是说,自1989年起,ANSI C标准化,如果我们有:

#if foo + bar - xyzzy

该指令受宏替换的影响,因此如果foobarxyzzy是宏,则替换它们。然后,任何未替换的剩余标识符将替换为0。因此,如果将foo定义为42,但根本没有定义barxyzzy,我们会得到:

#if 42 + 0 - 0

而不是说语法错误:

#if 42 + -

或其他一些行为,例如关于bar未定义的诊断。

在未定义的宏被视为空白的预处理器上,#if SOMETHING_SUPPORTED扩展为#if,这是错误的。

这是IDENT+0这个技巧真正意义上的唯一方法。如果您可以依赖符合ISO C的预处理,那么您根本不会想要这样做。

原因是如果预期SOMETHING_SUPPORTED具有数值,则错误地将其分散为将其定义为空白。理想情况下,您希望检测何时发生这种情况,并使用诊断程序停止编译。

其次,如果你支持这种散乱的用法,你几乎肯定希望一个明确定义但空白的符号表现得好像它的值是1,而不是值0。 ,你正在创造一个陷阱。有人可能会在编译器命令行上执行此操作:

 -DSOMETHING_SUPPORTED=$SHELL_VAR  # oops, SHELL_VAR expanded to nothing

或代码:

 #define SOMETHING_SUPPORTED  /* oops, forgot "1" */

没有人会为某个符号添加一个#define-D,目的是让关闭它控制的功能!插入#define SOMETHING_SUPPORTED而没有1的程序员会对

的行为感到惊讶
 #if SOMETHING_SUPPORTED+0

跳过要启用的材料。

这就是为什么我怀疑很少有C程序员读过这个用法,为什么我怀疑它只是预处理器行为的一种解决方法,如果SOMETHING_SUPPORTED缺失,其预期效果是跳过块。它产生“程序员陷阱”的事实只是解决方法的副作用。

要在没有创建程序员陷阱的情况下解决这样的预处理器问题,请在翻译单元的早期某处:

#ifndef SOMETHING_SUPPORTED
#define SOMETHING_SUPPORTED 0
#endif

然后在其他地方使用#if SOMETHING_SUPPORTED。也许这种方法没有发生在原始程序员身上,或者程序员可能认为+0技巧很整洁,并且重视其自我控制。

答案 1 :(得分:44)

#if X+0 != 0被定义为空的情况下,

#if XX不同(注意:这与X未定义的情况不同),例如:

#define X

#if X          // error
#if X+0 != 0   // no error; test fails

定义空宏非常常见:项目配置可能会生成一些包含一堆行#define USE_FOO#define USE_BAR的公共标题,以启用系统支持的功能,等等。

!= 0是多余的,代码可能只是#if X+0

因此,使用#if X+0的好处是,如果将X定义为空,则继续编译,跳过该块,而不是触发错误。

这是否是一个好主意是值得商榷的,我个人会将#ifdef用于布局宏(如USE_SOME_FEATURE)和#if用于宏,其值可能是整数范围,例如;如果我不小心将#if与定义为空的东西一起使用,我希望看到一个错误。

答案 2 :(得分:35)

让我们做一张桌子!

X       #if X     #if X+0 != 0
<undef> false     false
<empty> error     false
0       false     false
1       true      true
2       true      true
a       false     false
xyz     false     false
12a     error     error
12 a    error     error

因此我们发现的唯一区别(感谢评论者)是定义了X但没有值的情况(如空字符串)。我之前从未见过+0 != 0变体。

答案 3 :(得分:7)

这是另一种写作方式

 #if defined(MACRO) && MACRO != 0

+0用于确保结果为数字。如果未定义MACRO,则会避免#if MACRO != 0导致的语法错误。

质量差的东西,但除非得到,否则不要惹它。