C 宏替换列表重新扫描以进行替换

C 宏替换列表重新扫描以进行替换,c,macros,preprocessor,C,Macros,Preprocessor,我正在阅读有关宏替换的标准N1570,并误解了6.10.3.4中的一些措辞 1替换列表中的所有参数后 和#和###处理已经完成,所有的placemarker预处理都已经完成 代币被移除。然后生成预处理令牌序列 重新扫描,以及 源文件,用于替换更多宏名称 因此,在所有#和##问题解决后,我们重新扫描替换列表。但第2节规定: 2如果在扫描过程中发现要替换的宏的名称 替换列表(不包括源文件的其余部分) 预处理令牌),它不会被替换。此外,如果有嵌套 替换遇到被替换宏的名称,但不是 替换 在我看来这是自相

我正在阅读有关宏替换的标准N1570,并误解了
6.10.3.4
中的一些措辞

1替换列表中的所有参数后 和#和###处理已经完成,所有的placemarker预处理都已经完成 代币被移除。然后生成预处理令牌序列 重新扫描,以及 源文件,用于替换更多宏名称

因此,在所有
#
##
问题解决后,我们重新扫描替换列表。但第2节规定:

2如果在扫描过程中发现要替换的宏的名称 替换列表(不包括源文件的其余部分) 预处理令牌),它不会被替换。此外,如果有嵌套 替换遇到被替换宏的名称,但不是 替换

在我看来这是自相矛盾的。那么在那次重新扫描中可能会有什么样的替换?我尝试了以下示例:

#define FOOBAR(a, b) printf(#a #b)

#define INVOKE(a, b) a##b(a, b)

int main() {
    INVOKE(FOO, BAR); //expands to printf("FOO" "BAR")
}
因此,
INVOKE(FOO,BAR)
在替换
#
之后扩展为
FOOBAR(FOO,BAR)
。然后重新扫描替换列表
FOOBAR(FOO,BAR)
。但是
2.
部分指定要替换的宏的名称(
FOOBAR
)被找到(是的,上面定义过),而不是被替换(但实际上被替换,如演示中所示)

你能澄清一下那句话吗?我错过了什么

被替换的(原始)宏不是
FOOBAR
,而是
INVOKE
。当您展开
INVOKE
并找到
FOOBAR
时,您通常会展开
FOOBAR
。但是,如果在展开
INVOKE
时找到了
INVOKE
,则它将不再展开

让我们看一下下面的代码:

#define FOOBAR(a, b) printf(#a #b)

#define INVOKE(a, b) e1 a##b(a, b)

int main() {
    INVOKE(INV, OKE);
}
我将
e1
添加到
INVOKE
的扩展中,以便能够可视化发生了多少扩展。预处理
main
的结果是:

e1 INVOKE(INV, OKE);
这证明
INVOKE
已展开一次,然后在重新扫描时不再展开


考虑以下简单示例:

#include<stdio.h>

const int FOO = 42;

#define FOO (42 + FOO) 

int main()
{
   printf("%d", FOO);
}
这意味着当宏
FOO
展开时,当找到第二个
FOO
时,展开将停止。它将不会进一步扩大。否则,您将以无休止的递归结束,结果是:
42+(42+(42+)(42+…)

现场演示

printf("%d", 42 + 42);