我猜你们大多数使用过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”就无法发生!
我的问题:我错过了什么?显然我不知道预处理器如何工作的确切方式。你知道有关它的任何消息来源吗?
答案 0 :(得分:13)
Self-Referential Macros解释道。扩展应用得很深,但一旦宏引用它就会停止。
答案 1 :(得分:5)
#define A B
#define B A C
#define C x
A -> B -> A C -> A x
B -> A C -> B x
扩展是令牌“懒惰”的标记
答案 2 :(得分:5)
每个替换链最多可以访问任何宏定义一次。除此之外,这意味着您不能拥有递归宏。
第二个示例的替换将如下所示:
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重新扫描和进一步更换。
答案 3 :(得分:3)
好吧,好吧,也许不是任何人都愿意的 期待,但这是可以解释的。我猜 预处理器不知怎的想法 表示存在一些问题,并且 没有。
不。如果预处理器执行扩展,则它仅扩展符号一次。因此,在A的第一个示例中:A将扩展为B,B扩展为A,此处扩展停止。在第二行中,B扩展为A,扩展为B,扩展停止,因为我们已经扩展了B.
如果您将逻辑应用于第二个示例,那么结果将立即变得明显。