C 预处理器中的递归是否滥用了标准中的不一致?

Hir*_*lot 5 c c++ language-lawyer c-preprocessor

考虑这段代码:

#define MAP_OUT

#define A(x) B MAP_OUT (x)
#define B(x) A MAP_OUT (x)

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

然后A(x)展开为B MAP_OUT (x), 那么B (x)。现在看一下标准:

在替换列表中的所有参数都已被替换并且 # 和 ## 处理已发生后,所有地标预处理标记都将被删除。然后重新扫描生成的预处理标记序列以及源文件的所有后续预处理标记,以查找更多要替换的宏名称。

是否B (x)属于“生成的预处理标记序列以替换更多宏名称”?我尝试过的所有编译器在单次扫描期间都不会扩展B (x),但是标准本身呢?

n. *_* m. 4

B(x) 是否属于“结果预处理标记序列以供更多宏名称替换”?

不,绝对不是。再读一遍:

在替换列表中的所有参数都已被替换并且 # 和 ## 处理已发生后,所有地标预处理标记都将被删除。然后重新扫描生成的预处理令牌序列。

由参数替换产生的预处理标记序列in A(x)是精确的B MAP_OUT (x),不多不少。然后扫描该序列以查找更多要替换的宏一次。那里只有一个符合条件的宏可以替换,MAP_OUT. 然后扫描替换MAP_OUT,没有发现任何内容,然后恢复处理。

没有任何迹象表明B应该B MAP_OUT (x)扫描两次。