Som*_*ame 9 c macros preprocessor
我正在读关于宏观替换的标准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")
}
Run Code Online (Sandbox Code Playgroud)
因此INVOKE(FOO, BAR),FOOBAR(FOO, BAR)在取代之后扩展到##.然后FOOBAR(FOO, BAR)重新扫描替换列表.但是该部分2.指定被替换的宏的名称(FOOBAR)是(是的,上面定义的)它没有被替换(但实际上被替换,如在演示中可以看到的).
你能澄清一下这个措辞吗?我错过了什么?
被替换的(原始)宏不是FOOBAR,它是INVOKE.当您进行扩展INVOKE并找到时FOOBAR,您可以FOOBAR正常扩展.但是,如果INVOKE在扩展时找到INVOKE它,它将不再扩展.
我们来看下面的代码:
#define FOOBAR(a, b) printf(#a #b)
#define INVOKE(a, b) e1 a##b(a, b)
int main() {
INVOKE(INV, OKE);
}
Run Code Online (Sandbox Code Playgroud)
我添加了e1扩展,INVOKE以便可视化发生了多少次扩展.预处理的结果main是:
e1 INVOKE(INV, OKE);
Run Code Online (Sandbox Code Playgroud)
这证明了INVOKE一次扩展然后在重新扫描后不再扩展.