首页 > 解决方案 > 为什么宏名称没有涂成蓝色?

问题描述

假设我有以下两个宏定义:

#define foo(X) 1 bar
#define bar(X) 2 foo

为什么要foo(X)(Y)(Z)展开为1 2 1 bar

根据 C99 标准 6.10.3.4 重新扫描和进一步替换

如果在替换列表的扫描过程中找到被替换的宏的名称(不包括源文件的其余预处理标记),则不会替换它。此外,如果任何嵌套替换遇到被替换的宏的名称,它不会被替换。这些未替换的宏名称预处理标记不再可用于进一步替换,即使它们稍后在该宏名称预处理标记将被替换的上下文中进行(重新)检查。

所以这些标记的翻译方式似乎是以下序列

foo(X)(Y)(Z)
1 bar(Y)(Z)
1 2 foo(Z)
1 2 1 bar

所以显然第二个宏调用foo不会被涂成蓝色。我有点不确定为什么会这样。它不是由调用引起的替换的一部分吗,bar它会使其成为第一次调用的替换的嵌套替换foo

我只能争辩说,这些扩展的工作方式是导致两者的宏调用的标记foo部分bar在嵌套替换中,即宏的名称在其中,部分在替换之外,即括号部分是在替换之外。

或者也许我完全误解了嵌套替换的含义。

有人能这么好心澄清一下吗。

标签: cc-preprocessorc99

解决方案


这里有 2 个替换阶段。首先发生在参数替换期间,它与文件的其余部分隔离发生:

6.10.3.1 参数替换

  1. 在确定了调用类函数宏的参数后,将进行参数替换。替换列表中的参数,除非前面有 # 或 ## 预处理标记或后跟 ## 预处理标记(见下文),在其中包含的所有宏都已展开后,将替换为相应的参数。在被替换之前,每个参数的预处理标记都被完全宏替换,就好像它们形成了预处理文件的其余部分一样; 没有其他可用的预处理令牌。

第二阶段,重新扫描,发生在宏之后,它的参数已经扩展:

6.10.3.4 重新扫描和进一步更换

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

您所指的段落仅适用于第一阶段,参数替换:

  1. 如果在替换列表的扫描过程中找到被替换的宏的名称(不包括源文件的其余预处理标记),则不会替换它。...

由于您的宏foobar使用它们的参数,因此您只看到重新扫描阶段的效果。


推荐阅读