为啥编译器抱怨这个宏声明

Posted

技术标签:

【中文标题】为啥编译器抱怨这个宏声明【英文标题】:Why compiler complain about this macro declaration为什么编译器抱怨这个宏声明 【发布时间】:2012-04-09 14:14:31 【问题描述】:

为了调试方便,我写了以下宏,

1 #ifndef DEF_H
2 #define DEF_H
3 #define DEBUG_MODE
4 #define DEBUG_INFO(message)     \
5         #ifdef DEBUG_MODE       \
6                 cout << message << endl; \
7         #endif                          \
8 #endif

但 gcc 抱怨如下

def.h:4: error: '#' is not followed by a macro parameter
def.h:1: error: unterminated #ifndef

这段代码有什么问题?我是否遗漏了一些重要的点?

【问题讨论】:

【参考方案1】:

您不能在宏定义中包含#ifdefs。你需要把它翻过来:

#ifdef DEBUG_MODE
#define DEBUG_INFO(message) cout << (message) << endl
#else
#define DEBUG_INFO(message)
#endif

【讨论】:

谢谢。那么如何使用宏来控制调试开关来实现目标。在客户端,我更喜欢只调用一行,例如 DEBUG_INFO("debug info") +1。另外,第 7 行后面有一个反斜杠,导致最后一行的 #endif 成为第 4 行的一部分,与第一行的 #ifndef 不匹配【参考方案2】:

您不能将预处理器指令嵌入另一个预处理器指令(DEBUG_INFO 定义中的#ifdef DEBUG_MODE)。相反,做类似的事情

#ifdef DEBUG_MODE
# define DEBUG_INFO(message) cout << message << endl
#else
# define DEBUG_INFO(message) 0
#endif

(这仍然不理想;防御性宏编码建议类似于

#ifdef DEBUG_MODE
# define DEBUG_INFO(message) do cout << message << endl; while (0)
#else
# define DEBUG_INFO(message) 0
#endif

也许inline 函数会更好。)

【讨论】:

“你不能在另一个预处理器指令中嵌入一个预处理器指令”,这并非适用于所有情况,是吗?例如#if、#ifdef 和 #ifndef【参考方案3】:

我猜如果你在第 7 行吃“\”,那段代码就可以工作了。

【讨论】:

以上是关于为啥编译器抱怨这个宏声明的主要内容,如果未能解决你的问题,请参考以下文章

Kotlin 编译器抱怨在属性定义中使用 SPeL 表达式。为啥?

编写 if-else 编译器时会抱怨,但简而言之却没有,为啥? [复制]

Linux 上 Poco::Logger 的编译器错误 - 函数声明被视为宏

为啥 MSVC 在编译宏时大发雷霆,而 G++ 完全是关于禅的?

为啥不包含头文件却可以调用函数,谁来解释

为啥 int main() 编译?