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

Macro replacement list rescanning for replacement

提问人:Some Name 提问时间:1/15/2019 更新时间:1/15/2019 访问量:530

问:

我正在阅读有关宏替换的标准 N1570,并误解了 .6.10.3.4

1 替换列表中的所有参数都替换完毕后 和 # 和 ## 处理已发生,所有地标预处理 令牌将被删除。然后,生成的预处理令牌序列为 重新扫描,以及 源文件,用于替换更多宏名称

因此,在解决之后,我们重新扫描替换列表。但第 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

你能否澄清一下措辞?我错过了什么?

现场演示

C 宏预 处理器

评论


答:

9赞 Angew is no longer proud of SO 1/15/2019 #1

被替换的(原始)宏不是 ,而是 。当你在扩张时,你发现,你正常扩张。但是,如果在扩展时发现了,则将不再扩展。FOOBARINVOKEINVOKEFOOBARFOOBARINVOKEINVOKE

让我们采用以下代码:

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

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

int main() {
    INVOKE(INV, OKE);
}

我添加了 的扩展,以便能够可视化发生了多少扩展。预处理的结果是:e1INVOKEmain

e1 INVOKE(INV, OKE);

这证明它被扩展了一次,然后在重新扫描时,没有再次扩展。INVOKE

[现场示例]

4赞 P.W 1/15/2019 #2

请看以下简单示例:

#include<stdio.h>

const int FOO = 42;

#define FOO (42 + FOO) 

int main()
{
   printf("%d", FOO);
}

此处的输出将为 84。

将扩展到:printf

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

这意味着当宏被展开时,当找到第二个时,扩展将停止。它不会进一步扩大。否则,你最终会得到无休止的递归,导致:FOOFOO42 + (42 + (42 + (42 + ....)

现场演示在这里