【问题标题】:(Weird?) GCC Preprocessor Behaviour(奇怪?)GCC 预处理器行为
【发布时间】:2011-06-16 20:52:21
【问题描述】:

我猜大多数使用过 C/C++ 的人都对预处理器的工作原理(或多或少)有直觉。直到今天我都这么认为,但事实证明我的直觉是错误的。故事如下:

今天我尝试了一些东西,但我无法解释结果。 首先考虑以下代码:

#define A B
#define B A

A
B

会发生什么?嗯,用-E标志编译后的结果是这样的:

A
B

嗯,好吧,也许不是任何人所期望的,但这是可以解释的。我猜是预处理器发现了一些问题,然后什么也没做。

接下来我尝试的是这样的:

#define A B
#define B A C
#define C x

A
B

现在,对我来说,无法解释的结果:

A x
B x

这是怎么发生的?我无法弄清楚这是如何发生的任何合理的方式。第一个命令 (#define A B) 无法执行,因为 A 将被 B 替换,最终结果应该相同。但如果不是,那么“A x”就不可能发生!

我的问题:我错过了什么?显然我不知道预处理器如何工作的确切方式。你知道它的任何来源吗?

【问题讨论】:

  • 这就是为什么#defines需要避免......
  • 是的,这是另一个原因.. 并不是说​​我根本不使用它们。对于某些任务,它们非常有用(也是 i.m.o. 的方法)。

标签: gcc c-preprocessor


【解决方案1】:

Self-Referential Macros 解释。扩展被深度应用,但一旦宏引用自身就会停止。

【讨论】:

  • 链接好像坏了
【解决方案2】:
#define A B
#define B A C
#define C x

A -> B -> A C -> A x 
B -> A C -> B x

扩展是一个令牌一个令牌“懒惰地”

【讨论】:

    【解决方案3】:

    每个替换链最多可以访问任何宏定义一次。除此之外,这意味着您不能使用递归宏。

    第二个示例的替换将如下所示:

    A --[evaluate A]--> B --[evaluate B]--> A C --[evaluate C]--> A x
    B --[evaluate B]--> A C --[evaluate A,C]--> B x
    

    在第一行的最后一步,A 未被评估,因为它之前已经被调用过。同样,在第二行中,求值在B 处停止,因为它已经在第一步中被访问过。

    C99 标准的相关部分将是6.10.3.4 重新扫描和进一步替换

    【讨论】:

    • 感谢您的解释!我在语法和语言的背景下思考,我完全错过了那个明显的解释。
    【解决方案4】:

    嗯,好吧,也许不是任何人都会的 期待,但这是可以解释的。我猜 预处理器以某种方式认为 有一些问题,并且 什么都没做。

    不。如果预处理器进行扩展,它只会将符号扩展一次。因此,在 A 的第一个示例中:A 扩展为 B,B 扩展为 A,此处扩展停止。在第二行中,B 扩展为 A,A 扩展为 B,扩展停止,因为我们已经扩展了 B。

    如果您将逻辑应用于第二个示例,那么结果会立即变得显而易见。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-01
      • 2017-03-29
      • 2011-02-06
      • 2023-03-10
      • 2011-03-23
      相关资源
      最近更新 更多