(很奇怪?)GCC预处理器行为

Geo*_*rge 13 gcc c-preprocessor

我猜你们大多数使用C/C++的人都对预处理器的工作原理有所了解(或多或少).直到今天我才这么想,但我的直觉被证明是错误的.这是故事:

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

#define A B
#define B A

A
B
Run Code Online (Sandbox Code Playgroud)

怎么了?好吧,用-E标志编译后的结果如下:

A
B
Run Code Online (Sandbox Code Playgroud)

嗯,好吧,也许不是任何人都会想到的,但这是可以解释的.我猜这个预处理器以某种方式弄清楚存在一些问题,而且没有问题.

我尝试的下一件事是这样的:

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

A
B
Run Code Online (Sandbox Code Playgroud)

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

A x
B x
Run Code Online (Sandbox Code Playgroud)

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

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

eph*_*ent 13

自引用宏解释道.扩展应用得很深,但一旦宏引用自身就会停止.


Any*_*orn 5

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

A -> B -> A C -> A x 
B -> A C -> B x
Run Code Online (Sandbox Code Playgroud)

扩展是令牌"懒惰"的象征


Chr*_*oph 5

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

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

A --[evaluate A]--> B --[evaluate B]--> A C --[evaluate C]--> A x
B --[evaluate B]--> A C --[evaluate A,C]--> B x
Run Code Online (Sandbox Code Playgroud)

在第一行的最后一步中,A未评估,因为它之前已被调用.类似地,在第二行中,评估停止,B因为它已在第一步中访问过.

C99标准的相关部分为6.10.3.4重新扫描和进一步更换.