为什么这个连接宏需要一个间接级别?

Dao*_*Wen 18 c macros concat

我找到了一篇有趣的小博文,解释了如何使用行号在宏中生成(半)唯一名称:

// 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
Run Code Online (Sandbox Code Playgroud)

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

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

我有一种感觉,这两个问题的答案是相关的,并且与C预处理器评估宏的方式有关.(但是,由于我甚至认为这个例子无效,我对宏如何工作的直觉显然已经过时了.)

mas*_*oud 12

为什么如果在文件中声明JOIN后,LINE_NAME宏甚至可以工作?

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

为什么有必要同时使用JOIN和_DO_JOIN宏来获得正确的结果?在宏中具有这种间接级别似乎很奇怪.

因为__LINE__它本身就是一个宏,所以它需要两个级别的扩展.

否则,输出是不是prefix1234这将是prefix__LINE__.

阅读这个答案也很有用,这个帖子.

  • @道文:是的。确切的规则是:如果你有一个宏定义 `#define FOO(x, ...) ...`,那么任何参数 `x` 都会被递归扩展 * 除非它是字符串化或标记粘贴运算符的参数*(`#` 和`##`)。参见 C99 §6.10.3.1/1。 (2认同)