【问题标题】:C preprocessor tokenization does not expand macro?C预处理器标记化不扩展宏?
【发布时间】:2025-11-24 21:05:01
【问题描述】:

1) 为什么宏MSG在下面的表达式中没有展开?

#define MSG Hello
#define HELLO(name)  MSG ## name

void HELLO(Dave) () {}

使用

gcc -E -P test.cpp 

输出:

void MSGDave () {}

MSG name 扩展为 Hello DaveMSG # name 扩展为 Hello "Dave"。那么是什么原因导致 gcc 不展开MSG ## name呢?

2) 有解决方法吗?

有没有像defined(x)这样的预处理指令,比如expand(x)?

【问题讨论】:

    标签: c gcc macros c99 c-preprocessor


    【解决方案1】:

    因为宏参数在## 运算符之前或之后不会被替换。

    C11 §6.10.3.1 参数替换

    在确定了调用类函数宏的参数后,将进行参数替换。替换列表中的一个参数,除非前面有 ### 预处理令牌或后跟 ## 预处理令牌(见下文), 在其中包含的所有宏都已展开后,由相应的参数替换。在被替换之前,每个参数的预处理标记都被完全宏替换,就好像它们形成了预处理文件的其余部分一样;没有其他可用的预处理令牌。

    【讨论】:

    • 不错。你解决了一半的问题——为什么它没有被扩展。然后@n.m。给出了另一个非常重要的部分——解决方法。
    【解决方案2】:
    #define MSG Hello
    #define cat(x, y) x ## y
    #define cat2(x, y) cat(x, y)
    #define HELLO(name) cat2(MSG,name)
    

    Live demo @ ideone.

    【讨论】:

    • 太棒了!这是答案的第二个也是最重要的一半 - 解决方法。 @Yu 首先回答了原因——这个“错误”是设计使然。