You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

类函数宏嵌套调用的C预处理器展开规则疑问

C 互调宏展开规则常见误解解答

首先给出你提到的代码片段:

#define FOO() BAR
#define BAR() FOO

FOO()()()

核心理解疏漏

你对宏展开时的禁用规则范围理解有误:C99 6.10.3.4p2 规定的「展开过程中忽略当前宏名称」,仅适用于本次宏展开生成的替换列表本身的标记,不包括替换后紧跟的其他源文件标记,也不会作用于其他宏展开生成的标记。也就是说,只有在当前正在展开的宏的替换列表扫描过程中,出现和当前宏同名的标记才会被跳过,其他场景下的同名宏标记都可以正常识别展开。

完整展开步骤拆解

我们按标准规则一步步走整个展开流程:

  1. 初始预处理标记序列:FOO ( ) ( ) ( )
  2. 匹配到第一个宏调用FOO(),将FOO ( )三个标记替换为BAR,得到新序列:BAR ( ) ( )。此时仅在扫描BAR这个FOO的替换标记时,FOO会被禁用,后续的括号属于源文件剩余标记,不受FOO禁用规则影响。
  3. 重扫新序列,匹配到BAR()宏调用,将BAR ( )替换为FOO,得到新序列:FOO ( )。此时仅在扫描FOO这个BAR的替换标记时,BAR会被禁用,FOO本身没有被当前流程禁用。
  4. 再次重扫新序列,匹配到FOO()宏调用,该FOO是BAR展开生成的标记,不属于最初FOO展开的替换列表范围,因此可以正常展开为BAR,得到最终结果。

补充说明

你之前误以为只要是最初FOO展开间接产生的FOO标记都会被永久禁用,这是对标准规则的扩大化理解。标准的禁用规则本质是为了避免无限递归展开,仅限制同一个宏在自己的替换列表中直接/间接调用自己,不会限制不同宏交替展开时重新调用外层宏。

内容的提问来源于stack exchange,提问作者koorkevani

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.01 01:39:02