为什么要用MACRO + 0!= 0

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

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

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

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

 #if SOMETHING_SUPPORTED ... #endif 

你知道为什么要用#if MACRO+0 != 0代替#if MACRO

这里的线索是代码库很老。

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

也就是说,从1989年的ANSI C开始,如果我们有以下标准,

#if foo + bar – xyzzy

该指令受macros代替,所以如果foobarxyzzy是macros,它们将被replace。 然后任何未被replace的剩余标识符被replace为0 。 所以如果foo被定义为42 ,但是barxyzzy完全没有定义,我们得到:

 #if 42 + 0 - 0 

而不是,不好的语法:

 #if 42 + - 

或者其他一些行为,比如关于bar诊断没有被定义。

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

这是IDENT+0技巧具有真正意义的唯一方法。 如果您可以依靠ISO C标准进行预处理,您根本就不会想要这样做。

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

其次,如果你确实支持这种散布的用法,那么你几乎可以肯定需要一个明确定义的空白符号,其行为就好像它的值为1,而不是值为0.否则,你正在创build一个陷阱。 有人可能会在编译器命令行上执行此操作:

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

或在代码中:

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

没有人会添加一个符号的定义或-D的目的是closures它控制的function! 插入#define SOMETHING_SUPPORTED而不是1的程序员会对

  #if SOMETHING_SUPPORTED+0 

这跳过了打算启用的材料。

这就是为什么我怀疑几乎没有C程序员读过这样的用法,为什么我怀疑这只是一个预处理器行为的解决方法,如果SOMETHING_SUPPORTED丢失,其预期效果是跳过该块。 它造成“程序员陷阱”的事实只是解决方法的一个副作用。

要解决这样一个预处理器问题,而不是创build一个程序员陷阱,在翻译单元的早期某个地方可以这样做:

 #ifndef SOMETHING_SUPPORTED #define SOMETHING_SUPPORTED 0 #endif 

然后在其他地方使用#if SOMETHING_SUPPORTED 。 原来程序员也许没有这样做,也许这个程序员认为+0技巧是整洁的,并且把自己的价值放在了自我控制上。

#if X+0 != 0X被定义为空的情况下(注意:这与X未被定义的情况不同) #if X是不同的,例如:

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

定义空白macros是很常见的:项目configuration可能会生成一些常见的头文件,其中包含许多行#define USE_FOO#define USE_BAR以启用系统支持的function等等。

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


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

这是一个好主意是有争议的,我个人会使用#ifdef布尔macros如USE_SOME_FEATURE#ifmacros的值可能是一个整数范围,例如; 如果我不小心使用#if来定义空的话,我会想看到一个错误。

我们来一张桌子吧!

 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被定义但没有值的情况(如空string)。 我从来没有见过+0 != 0变种。

这是另一种写作方式

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

+0是确保结果是一个数字。 如果未定义MACRO则避免了由于#if MACRO != 0而导致的语法错误。

质量差的东西,但不要惹它,除非你必须。