如何定义使用另一个宏的 C 宏?
How to define a C macro that uses another macro?
我有以下场景...
头文件:
#define TRIG_INDEX 200
#define PATH(target_p) some.path.to.target##target_p
源文件:
read_from_target(PATH(TRIG_INDEX));
由于 PATH
宏将 target_p
附加到末尾的文本,因此编译失败
some.path.to.targetTRIG_INDEX
不是有效路径。
在上述情况下,我希望得到 read_from_target(some.path.to.target200)
。
我如何(如果有的话)定义宏来接受这种情况?
参数必须被宏扩展:
#define TRIG_INDEX 200
#define PATH_TARGET(x) some.path.to.target##x
#define PATH(target_p) PATH_TARGET(target_p)
类函数宏的预处理器宏 expansion/replacement 规则相当复杂。基本上它按以下顺序执行:
宏名称后面的内容称为替换列表。在这种情况下 PATH_TARGET(target_p)
- PATH
应该替换为
##
或 #
与宏参数一起出现意味着该参数被替换为其相应的预处理器标记序列(如果适用)。在这种情况下,参数 target_p
被替换为 TRIG_INDEX
,因此我们得到 some.path.to.target##TRIG_INDEX
创建新的预处理器令牌 some.path.to.targetTRIG_INDEX
,这不是预期的。
其他宏参数得到扩展。不适用于此处。
然后 重新扫描 替换列表以扩展宏名称,但为时已晚,因为与 ##
的预处理器标记连接已经完成发生了。
上面“扩展其他宏参数”部分对解决问题很有用。因此替换列表中的宏 parameters 优先于宏 names。我们可以通过添加辅助宏来利用这一点:
#define TRIG_INDEX 200
#define EXPAND(tgt) some.path.to.target##tgt
#define PATH(target_p) EXPAND(target_p)
现在在扩展PATH
的替换列表中,首先得到宏参数扩展:taget_p
被替换,得到EXPAND(TRIG_INDEX)
。然后重新扫描替换列表以查找要替换的宏名称,预处理器找到两个这样的宏名称:EXPAND
和 TRIG_INDEX
。两者都已扩展,因此 TRIG_INDEX
被替换为 200
。然后根据相同的规则递归扩展 EXPAND
(##
强制将该宏参数 tgt
扩展到 200
之前)。
有关详细信息,请参阅 C17 标准第 6.10.3 章 - 这一章也是指定 # 和 ## 运算符行为的一章。
我有以下场景...
头文件:
#define TRIG_INDEX 200
#define PATH(target_p) some.path.to.target##target_p
源文件:
read_from_target(PATH(TRIG_INDEX));
由于 PATH
宏将 target_p
附加到末尾的文本,因此编译失败
some.path.to.targetTRIG_INDEX
不是有效路径。
在上述情况下,我希望得到 read_from_target(some.path.to.target200)
。
我如何(如果有的话)定义宏来接受这种情况?
参数必须被宏扩展:
#define TRIG_INDEX 200
#define PATH_TARGET(x) some.path.to.target##x
#define PATH(target_p) PATH_TARGET(target_p)
类函数宏的预处理器宏 expansion/replacement 规则相当复杂。基本上它按以下顺序执行:
宏名称后面的内容称为替换列表。在这种情况下
PATH_TARGET(target_p)
-PATH
应该替换为##
或#
与宏参数一起出现意味着该参数被替换为其相应的预处理器标记序列(如果适用)。在这种情况下,参数target_p
被替换为TRIG_INDEX
,因此我们得到some.path.to.target##TRIG_INDEX
创建新的预处理器令牌some.path.to.targetTRIG_INDEX
,这不是预期的。其他宏参数得到扩展。不适用于此处。
然后 重新扫描 替换列表以扩展宏名称,但为时已晚,因为与
##
的预处理器标记连接已经完成发生了。
上面“扩展其他宏参数”部分对解决问题很有用。因此替换列表中的宏 parameters 优先于宏 names。我们可以通过添加辅助宏来利用这一点:
#define TRIG_INDEX 200
#define EXPAND(tgt) some.path.to.target##tgt
#define PATH(target_p) EXPAND(target_p)
现在在扩展PATH
的替换列表中,首先得到宏参数扩展:taget_p
被替换,得到EXPAND(TRIG_INDEX)
。然后重新扫描替换列表以查找要替换的宏名称,预处理器找到两个这样的宏名称:EXPAND
和 TRIG_INDEX
。两者都已扩展,因此 TRIG_INDEX
被替换为 200
。然后根据相同的规则递归扩展 EXPAND
(##
强制将该宏参数 tgt
扩展到 200
之前)。
有关详细信息,请参阅 C17 标准第 6.10.3 章 - 这一章也是指定 # 和 ## 运算符行为的一章。