“#if Foo - 0 == 0”和“#if defined(Foo) && Foo == 0”有啥区别?

Posted

技术标签:

【中文标题】“#if Foo - 0 == 0”和“#if defined(Foo) && Foo == 0”有啥区别?【英文标题】:What is the difference between "#if Foo - 0 == 0" and "#if defined(Foo) && Foo == 0"?“#if Foo - 0 == 0”和“#if defined(Foo) && Foo == 0”有什么区别? 【发布时间】:2013-01-04 23:01:11 【问题描述】:

在qt documentation 中找到它。 有什么区别

#if defined(Foo) && Foo ==  0

#if Foo - 0 ==  0

据我了解,如果 Foo 未定义,后者也将是错误的?我在哪里可以阅读到这方面的信息?

【问题讨论】:

【参考方案1】:

如果Foo未定义,则后者将转换为

#if 0 - 0 == 0

这是,不是假的。请记住,在#if 下,所有未定义的标识符都被替换为文字0(当然,一旦所有defined() 运算符都被评估)。这甚至适用于匹配语言关键字的预处理标记。在 C 语言中,在此上下文中,所有关键字都替换为 0。在 C++ 中,关键字truefalse 可以免于替换,而所有其他关键字都会被替换。

(顺便说一句,这意味着在 C 中,如果不包含 <stdbool.h>,则 true 将悄悄替换为 0,如果包含 <stdbool.h>,则将替换为 1。)

同时

#if defined(Foo) && Foo == 0
Foo 未定义时,

为假。所以,这就是你的不同之处。

Qt 文档似乎确实表明前者与后者相同。我不知道他们为什么要这样做,因为它们肯定是不等价的。这似乎是 Qt 文档中的错误。

【讨论】:

所以 Qt 文档中有一个错误! '因为从他们的解释中可以看出这两者是相等的 all undefined identifiers are replaced with literal 0+1 @billz 和 AndreyT 你能和我分享一些关于 C++ 宏的链接或建议文章吗?因为我发现的只是它们的列表和简要描述,但我肯定没有读过诸如“所有未定义的标识符都替换为文字 0”之类的东西。 这是标准中的实际规则:“在由于宏扩展和defined一元运算符执行了所有替换之后,所有剩余的标识符和关键字,除了truefalse , 替换为 pp-number 0,然后将每个预处理令牌转换为一个令牌。”第 16.1p4 节 ISO/IEC 14882:2011(C++ 标准)§16.1 条件包含说:¶4 在评估之前,预处理标记列表中将成为控制常量表达式的宏调用被替换(除了那些被定义的一元运算符修改的宏名称),就像在普通文本中一样。 [...]由于宏扩展和定义的一元运算符执行了所有替换后,所有剩余的标识符和关键字,除了 true 和 false,都替换为 pp-number 0,然后将每个预处理标记转换为一个令牌。【参考方案2】:

Foo == 0 和 Foo - 0 == 0 的区别在于前者必须用值来定义 Foo:

#define Foo 0

不能是:

#define Foo  //  Foo == 0 would give an error, cannot evaluate Foo

虽然在 Foo - 0 == 0 的情况下,Foo 可以在没有值的情况下定义

所以:

#if defined(Foo) && Foo ==  0

表示 Foo 已定义并且它有一个值(在这种情况下为 0)。

和:

#if Foo - 0 ==  0

意味着 Foo 要么用 0 定义,要么不带值定义,但由于它不像第一种情况那样具有 defined(Foo),因此 Foo undefined 也将适用。

【讨论】:

以上是关于“#if Foo - 0 == 0”和“#if defined(Foo) && Foo == 0”有啥区别?的主要内容,如果未能解决你的问题,请参考以下文章

IF在Excel中的功能

异常机制

shell if [ -d filename]

js JS 浮点计算BUG

日期合法性

Linux基础