c - C预处理器中的嵌套##运算符

标签 c macros c-preprocessor string-concatenation

案例 1)

#define CONCATENATE(x,y) x##y

CONCATENATE(a,CONCATENATE(b,c)) 给出 aCONCATENATE(b,c)。

案例 2)

 #define CONCATENATE(x,y) x##y
 #define CONCATENATE2(x,y) CONCATENATE(x,y)

CONCATENATE2(a,CONCATENATE2(b,c)) 给出 abc。

为什么案例 1 不起作用?而案例 2 呢?
请逐步解释。

最佳答案

GCC 文档是这样解释的:

Macro arguments are completely macro-expanded before they are substituted into a macro body, unless they are stringified or pasted with other tokens.

(强调)

另一方面,##(标记粘贴)运算符的操作数在粘贴在一起之前不会进行宏扩展。所以,给定

CONCATENATE(a,CONCATENATE(b,c))

预处理器在展开外部宏的主体之前不会展开CONCATENATE(b,c),因为它是## 的操作数。预处理器在重新扫描更多要扩展的宏之前执行标记粘贴,所以

a ## CONCATENATE(b,c)

成为

aCONCATENATE(b,c)

在重新扫描之前,没有宏 aCONCATENATE(但如果有,那么会被扩展)。

另一方面,与

CONCATENATE2(a,CONCATENATE2(b,c)),

参数 CONCATENATE2(b,c) 不是 ##(或 #)运算符的操作数,因此它在被替换到宏主体之前被扩展,最终产生

CONCATENATE(a, bc)

作为外部宏的第一个扩展。重新扫描以进一步扩展,产生

abc

关于c - C预处理器中的嵌套##运算符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26284393/

相关文章:

c - 如何在 Visual Studio 2013 中修复 "differs in level of indirection"

ios - 何时在Objective-C中使用宏

c - x 宏打印错误的 offsetof() 信息

Cpp : How to understand and/or debug complex macros?

c - 制作一个接受C中任何类型的动态数组

c - 使用套接字通过C中的SOCKS5代理服务器发送请求

macros - 如何在仅使用 rustc 进行代码分析的现有项目中获得与 Cargo 类似的依赖项解析?

c - 带参数的通用多行宏

c - 没有宏的双链表的foreach?

c - 运行 C 可执行文件时 argv[0] 的精确值