【问题标题】:Why is a level of indirection needed for this concatenation macro?为什么这个串联宏需要一个间接级别?
【发布时间】:2013-11-09 01:48:52
【问题描述】:

我发现 an interesting little blog post 解释了如何使用行号在宏中生成(半)唯一名称:

// Do magic! Creates a unique name using the line number
#define LINE_NAME( prefix ) JOIN( prefix, __LINE__ )
#define JOIN( symbol1, symbol2 ) _DO_JOIN( symbol1, symbol2 )
#define _DO_JOIN( symbol1, symbol2 ) symbol1##symbol2

这里有两件事让我很困惑:

  1. 为什么LINE_NAME 宏即使在文件中声明了JOIN 之后也能工作?我认为 C 预处理器进行了线性传递,因此需要根据依赖关系定义宏,就像在使用 C 函数之前需要定义它们一样。
  2. 为什么必须同时使用JOIN_DO_JOIN 宏才能获得正确的结果?在宏中使用这种间接级别似乎很奇怪。

我感觉这两个问题的答案是相关的,并且与 C 预处理器评估宏的方式有关。 (但是,我对宏如何工作的直觉显然是错误的,因为我什至不认为这个例子是有效的。)

【问题讨论】:

标签: c macros concat


【解决方案1】:

为什么 LINE_NAME 宏即使在文件中声明 JOIN 之后也能工作?

宏不是函数,当你调用它们时编译器会扩展它们,并且在使用点的编译器知道所有定义的宏。

为什么必须同时使用 JOIN 和 _DO_JOIN 宏才能获得正确的结果?在宏中使用这种间接级别似乎很奇怪。

因为__LINE__本身就是一个宏,所以需要两级扩展。

否则输出不是prefix1234,而是prefix__LINE__

阅读this answerthis thread 也很有用。

【讨论】:

  • 好的,所以额外的宏本质上只是强制预处理器对结果字符串进行另一个查找/替换传递。如果JOIN(prefix, __LINE__) 的结果也恰好匹配一个宏名称,那它也会被替换吗?
  • @DaoWen:是的。确切的规则是:如果您有一个宏定义 #define FOO(x, ...) ...,那么任何参数 x 都会递归扩展除非它是字符串化或标记粘贴运算符的参数# 和 @ 987654330@)。见 C99 §6.10.3.1/1。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-12-25
  • 1970-01-01
  • 2011-08-05
  • 1970-01-01
  • 2011-08-27
  • 2011-12-07
相关资源
最近更新 更多