我想在一个被调用的宏中替换一些令牌,但似乎无法确定扩展和\或延迟的正确顺序。例如:
#define EXPAND(...) __VA_ARGS__
#define REPLACE(hello,y) EXPAND(y)
REPLACE(goodbye, hello world)
在我看来,REPLACE
宏将调用EXPAND
宏,使其功能相同:
#define REPLACE(hello,y) hello world
允许hello world
转变为goodbye world
。
我的编译器(MSVC 2017)似乎没有这样做,所以我怀疑我在这里错了。我已经阅读了扩展和推迟,并尝试了许多不同的DEFER()
和EXPAND()
组合,但似乎都没有给出我追求的结果。
有没有人对我做错了什么有任何见解?
这不是宏参数的处理方式,也不是原因。如果可以替换在宏的参数中使用宏参数名,那么就不可能编写安全的宏:不小心使用宏参数的名称会导致混乱,并且没有理由为什么宏调用者需要知道参数的名称是什么。宏参数是宏扩展的本地参数,类似于函数体的本地函数参数的方式。
这是C标准的§6.10.3.1/ 1 [Argument Substitution]中的实际替换算法:
在确定了调用类函数宏的参数之后,发生了参数替换。在扩展了包含在其中的所有宏之后,替换列表中的参数...被相应的参数替换。在被替换之前,每个参数的预处理标记都被完全宏替换,好像它们形成了预处理文件的其余部分;没有其他预处理令牌可用。
请注意,在放入宏扩展之前,参数是宏替换的。完成后,替换列表中的参数名称不再相关,并且不是替换文本的一部分。
一旦宏调用被其扩展替换,然后再次扫描生成的标记(第6.10.3.4节:“然后重新扫描生成的预处理标记序列,以及源文件的所有后续预处理标记,以获得更多的宏名称更换。”)。但是,由于在此重新扫描之前已完全替换宏调用,因此不再显示参数标记。
所以这个问题的特殊解决方案是一个死胡同。我建议您备份一个步骤并专注于您实际想要解决的问题。