在使用'宏定义集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)
。
要测试这一点,您可以省略后面的一些声明并对文件进行预处理。这会告诉你到底发生了什么