C/ c++预处理歧义



在使用'宏定义集1'执行以下代码时,我遇到错误"C2065: 'C1':未声明的标识符"。

当使用'Macro Definitions Set 2'时,代码的输出为2。

我猜它与预处理器标记化有关。请解释。

#include <iostream>
// Macro Definitions Set 1
#define A       1
#define D(n)    B(n)
#define B(n)    C##n
#define CA      2
// Macro Definitions Set 2
//#define A     1
//#define D(n)  C##n
//#define CA        2
int main ()
{
    printf ("%d", D(A));
}

除非宏参数在##之前或之后,或#之后,否则将被替换。

所以在Set 1中,D(n)被替换为B(1), CC_5被重新扫描后被替换为C1

在Set 2中,D(A)变为CA,其中A因为在##之后而没有被替换,CA重新扫描后变为2

使用第一组宏:

#define A       1
#define D(n)    B(n)
#define B(n)    C##n
#define CA      2

D(A)通过对A执行宏替换,然后将其替换到D(n)的替换列表中来求值。宏替换的结果是1,因此得到B(1)。然后递归计算B(1),得到C##1,它被连接到预处理令牌C1

使用第二组宏:

#define A     1
#define D(n)  C##n
#define CA    2

当计算D(A)时,对参数n的宏替换是而不是,因为它以##为前缀。这将得到C##A,从而得到预处理令牌CA。然后重新检查要替换的宏,结果是2 .

您需要在解析过程中经历每个阶段。基本上,预处理器进行迭代搜索和替换,直到用完标记(它可能更复杂,但就当前目的而言,就是这样做的)。每一行从左到右。

现在,使用set 2会发生什么:

  • printf("%d", D(A)); <-找到的第一个预处理器令牌是D(A),所以:
  • printf("%d", CA);
  • D(A)0

set 1:

  • printf("%d", D(A)); <-找到的第一个预处理器令牌是D(A),所以:
  • printf("%d", B(A)); <-现在,找到的下一个令牌是A
  • printf("%d", B(1));
  • printf("%d", C1); <- and error

问题是替换发生了,然后预处理器下一个找到A(可能不重新启动行)并执行另一个替换。然后它又去了一遍,但找到了B(1)

要测试这一点,您可以省略后面的一些声明并对文件进行预处理。这会告诉你到底发生了什么