C99宏展开示例疑问:为何f(z)展开结果非f(z[0][0])
你的推导错误点解析
首先明确C99宏替换的核心规则,尤其是递归阻止和标记机制:
1. 参数z的展开过程已触发递归阻止
当处理f(z)的参数替换时,实参z会先被展开:
- 启动宏
z的展开,此时z会被标记为「正在展开」。 - 展开
z得到z[0],接下来重新扫描这个结果。 - 扫描到
z[0]里的z时,因为它是当前正在展开的宏(z),所以不会被再次展开,并且这个未被替换的z会被标记为「永久不可再替换」——即使后续不在z的展开过程中,也不会被处理。 - 最终实参
z的展开结果就是z[0],而非无限递归的z[0][0]...。
2. 宏f的替换与重新扫描规则
将展开后的实参z[0]代入宏f的体f(a),得到f(z[0]):
- 进入重新扫描阶段时,当前正在处理的宏是
f,所以扫描到f(z[0])里的f时,会触发递归阻止,不会再次展开f。 - 而
z[0]里的z已经被标记为「永久不可再替换」,所以也不会被展开成z[0]。
你的推导错误根源
你忽略了两个关键规则:
- 宏展开时,当前正在展开的宏名称会被临时标记,其自身在本次展开过程中不会被递归替换,且未被替换的该宏token后续也无法再被替换。
- 参数
z的展开过程中,z[0]里的z已经触发了递归阻止并被标记为不可再替换,后续重新扫描时不会再处理这个z。
内容的提问来源于stack exchange,提问作者mdod
相关产品推荐
相关产品推荐

