为什么要用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代替,所以如果foo
, bar
或xyzzy
是macros,它们将被replace。 然后任何未被replace的剩余标识符被replace为0
。 所以如果foo
被定义为42
,但是bar
和xyzzy
完全没有定义,我们得到:
#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 != 0
在X
被定义为空的情况下(注意:这与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
和#if
macros的值可能是一个整数范围,例如; 如果我不小心使用#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
而导致的语法错误。
质量差的东西,但不要惹它,除非你必须。