在我目前的代码库中,我看到以下模式:
#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
,但bar
和xyzzy
所有没有定义,我们得到:
#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
变种.
这是另一种写作方式
#if defined(MACRO) && MACRO != 0
Run Code Online (Sandbox Code Playgroud)
+0用于确保结果为数字.如果MACRO
未定义,则可以避免由此产生的语法错误#if MACRO != 0
.
质量差的东西,但除非你得到,否则不要乱用它.