【问题标题】:How to define a C macro that uses another macro?如何定义使用另一个宏的 C 宏?
【发布时间】:2021-01-07 06:25:56
【问题描述】:

我有以下场景...

头文件:

#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)

我如何(如果有的话)定义宏来接受这种情况?

【问题讨论】:

  • 你需要一个额外的扩展步骤,例如见第二种情况here

标签: c macros


【解决方案1】:

参数必须由宏扩展:

#define TRIG_INDEX 200
#define PATH_TARGET(x) some.path.to.target##x
#define PATH(target_p) PATH_TARGET(target_p)

【讨论】:

    【解决方案2】:

    类函数宏的预处理器宏扩展/替换规则相当复杂。基本上它按以下顺序进行:

    • 宏名后面的东西被称为替换列表。在这种情况下,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)。然后重新扫描替换列表以查找要替换的宏名称,预处理器找到两个这样的宏名称:EXPANDTRIG_INDEX。两者都被扩展,因此TRIG_INDEX200 替换。然后 EXPAND 根据相同的规则递归扩展(## 强制将该宏参数 tgt 扩展为 200,然后再进行其他操作)。

    有关详细信息,请参阅 C17 标准第 6.10.3 章 - 这一章也是指定 # 和 ## 运算符的行为的一章。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-01-15
      • 2019-05-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-10-31
      相关资源
      最近更新 更多