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

Mir*_*pas 72 c c++

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

#if SOMETHING_SUPPORTED+0 != 0
...
#endif
Run Code Online (Sandbox Code Playgroud)

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

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

#if SOMETHING_SUPPORTED
...
#endif
Run Code Online (Sandbox Code Playgroud)

你知道为什么会使用#if MACRO+0 != 0而不是#if MACRO

Kaz*_*Kaz 70

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

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

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

#if foo + bar - xyzzy

该指令是受宏替换,这样,如果foo,bar或者xyzzy是宏,它们被替换.然后替换为未替换的任何剩余标识符0.所以,如果foo被定义为42,但barxyzzy所有没有定义,我们得到:

#if 42 + 0 - 0
Run Code Online (Sandbox Code Playgroud)

而不是说,语法错误:

#if 42 + -
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

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

 -DSOMETHING_SUPPORTED=$SHELL_VAR  # oops, SHELL_VAR expanded to nothing
Run Code Online (Sandbox Code Playgroud)

或在代码中:

 #define SOMETHING_SUPPORTED  /* oops, forgot "1" */
Run Code Online (Sandbox Code Playgroud)

没有人会添加一个#define-D一个符号,意图关闭它控制的功能!插入一个#define SOMETHING_SUPPORTED没有的程序员1会对行为感到惊讶

 #if SOMETHING_SUPPORTED+0
Run Code Online (Sandbox Code Playgroud)

跳过要启用的材料.

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

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

#ifndef SOMETHING_SUPPORTED
#define SOMETHING_SUPPORTED 0
#endif
Run Code Online (Sandbox Code Playgroud)

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


M.M*_*M.M 44

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

#define X

#if X          // error
#if X+0 != 0   // no error; test fails
Run Code Online (Sandbox Code Playgroud)

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

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


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

这是否是一个好主意是有争议的,我个人会#ifdef用于布尔宏,例如USE_SOME_FEATURE,#if对于宏,其中值可能是一个整数范围; 如果我不小心使用#if定义为空的东西,我会想看到一个错误.


Joh*_*nck 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
Run Code Online (Sandbox Code Playgroud)

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

  • 当`X`为空时,`#if X`为"错误" (2认同)

use*_*421 7

这是另一种写作方式

 #if defined(MACRO) && MACRO != 0
Run Code Online (Sandbox Code Playgroud)

+0用于确保结果为数字.如果MACRO未定义,则可以避免由此产生的语法错误#if MACRO != 0.

质量差的东西,但除非你得到,否则不要乱用它.

  • 这是不正确的:在`#define MACRO`之后,OP代码编译但你的版本没有 (8认同)