在当前的代码库中,我看到以下模式:
#if SOMETHING_SUPPORTED+0 != 0
...
#endif
不幸的是,这是一个非常古老的代码库,没人知道它是如何开始的。我认为它始于C,后来随着类逐渐转换为C,现在趋向于C ++
我看不到使用以前的构造而不是“经典”的任何明显优势,但是也许我缺少了一些东西:
#if SOMETHING_SUPPORTED
...
#endif
你知道为什么要用一个#if MACRO+0 != 0代替#if MACRO吗?
在当前的代码库中,我看到以下模式:
#if SOMETHING_SUPPORTED+0 != 0
...
#endif
不幸的是,这是一个非常古老的代码库,没人知道它是如何开始的。我认为它始于C,后来随着类逐渐转换为C,现在趋向于C ++
我看不到使用以前的构造而不是“经典”的任何明显优势,但是也许我缺少了一些东西:
#if SOMETHING_SUPPORTED
...
#endif
你知道为什么要用一个#if MACRO+0 != 0代替#if MACRO吗?
!= 0肯定是多余的
Answers:
这里的线索是代码库很旧。
之所以可能存在此技巧,是因为该代码曾经被移植到具有某些非常老的预处理器的编译器中,该预处理器在预处理器条件中不会将未定义的宏视为0 #if。
也就是说,从1989年ANSI C开始,我们标准化了以下条件:
#if foo + bar-xyzzy
该指令是受宏替换,这样,如果foo,bar或者xyzzy是宏,它们被替换。然后,将所有未替换的剩余标识符替换为0。所以,如果foo被定义为42,但bar和xyzzy所有没有定义,我们得到:
#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技巧很巧妙,并在其独立性上重视了价值。
-DTHING是速记-DTHING=1;如果您实际上希望宏扩展为无内容,则不必说-DTHING=。
-DFOO=$FOO_ON,其中shell var扩展为零,而不是预期的0或1!(已编辑)。
#if X+0 != 0是不同#if X的,其中的情况下X被定义为空(注意:这是的情况不同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定义为空的东西,我会希望看到一个错误。
-DNDEBUG将定义NDEBUG为1,不能为空。
-DNEBUG=将其定义为空
#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但没有值(例如空字符串)的情况。我以前从未见过这种+0 != 0变体。
#define X 1^2。
这是另一种写作方式
#if defined(MACRO) && MACRO != 0
那里+0以确保结果是数字。如果MACRO未定义,则可以避免引起的语法错误#if MACRO != 0。
质量低劣的东西,但是除非您必须,否则不要将其弄乱。
#if MACRO+0 !=0不是另一种写作方式#if defined(MACRO) && MACRO != 0。例如:#define MACRO将导致的构建错误#if defined(MACRO) && MACRO != 0并且会编译良好 #if MACRO+0 !=0
#define MACRO,OP代码会编译,但您的版本却无法编译