在子宏中替换父令牌

时间:2019-03-29 13:13:12

标签: c macros c-preprocessor preprocessor

我正在寻找在被调用的宏中替换一些令牌的方法,但似乎无法确定扩展和/或延迟的正确顺序。例如:

#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()的许多不同组合,但是似乎没有一个可以提供我想要的结果。

有人对我在做什么错有任何见识吗?

1 个答案:

答案 0 :(得分:0)

这不是处理宏参数的方式,这是有原因的。如果可以替换宏参数中使用的宏参数名称,则不可能编写安全的宏:意外使用宏参数名称会造成混乱,并且没有理由需要宏调用者知道参数的名称是什么。宏参数对于宏扩展是局部的,类似于函数参数对函数主体局部的方式。

这是来自C标准的6.10.3.1/1 [Argument Substitution]的实际替换算法:

  

在识别了调用类似函数的宏的参数之后,将进行参数替换。扩展列表中的所有宏均已扩展后,替换列表中的参数将由相应的参数替换。在被替换之前,每个参数的预处理令牌都被完全替换为宏,就好像它们构成了其余的预处理文件一样;没有其他预处理令牌可用。

请注意,在将参数放入宏扩展之前,将其替换为 。完成后,替换列表中的参数名称将不再相关,并且不再是替换文本的一部分。

一旦宏调用被其扩展替换,则再次扫描所得的令牌(第6.1.3.3.4节:“然后,重新扫描所得的预处理令牌序列以及源文件的所有后续预处理令牌,以获取更多信息。)替换的宏名称。”)。但是,由于在重新扫描之前已经完全替换了宏调用,因此参数标记不再出现。

因此,这种特殊的解决方案是死路一条。我建议您备份一个步骤,并专注于您实际希望解决的问题。