C++ 宏扩展的一个问题

One issue with c++ macro expand

本文关键字:一个 问题 扩展 C++      更新时间:2023-10-16

当我使用 g++ 编译 cpp 文件时,gcc 给出以下错误消息:

错误:粘贴"TBSYS_LOG_LEVEL_"和"-"未提供有效的预处理令牌

然后我检查了源代码,发现有三个宏定义:

  • 文件A.h中:
#define TBSYS_LOG_LEVEL_ERROR 0
#define TBSYS_LOG(level, _fmt_, args...) ((TBSYS_LOG_LEVEL_##level>TBSYS_LOGGER._level) ? (void)0 : TBSYS_LOG_BASE(level, "[%ld] " _fmt_, pthread_self(), ##args))
  • 文件B.h中:
#define ERROR -1

事实证明,在宏"TBSYS_LOG"展开之前,"ERROR"被扩展为"-1"。

展开"TBSYS_LOG_LEVEL_##level"后的结果是"TBSYS_LOG_LEVEL_-1",最后导致错误消息。

但是,据我所知,在这种情况下宏不会扩展。(使用 ## 时)

然后我写了另一个 cpp 文件来尝试这个:

#define FOOBAR 100
#define TEST(PARAM) FOO##PARAM
#define BAR -1
int main(){
    cout<<TEST(BAR)<<endl; 
}

这可以通过编译。输出为 100。这些宏的定义与前一个宏一样,但不会将"BAR"扩展到"-1",不会导致错误消息。

有谁知道为什么宏在前一种情况下会扩展?


更新:使用 TBSYS_LOG 的代码是:

TBSYS_LOG(ERROR, "expand data buffer failed, length: %d", bufsize);

#define FOOBAR 100
#define TEST(PARAM) FOO##PARAM
#define BAR -1
int main(){
    cout<<TEST(BAR)<<endl; 
}

##PARAM表示符号本身。所以TEST(BAR)这里展开为FOO##BAR(不是结果,只是为了解释),即FOOBAR,按#define FOOBAR 100,是100。

BAR永远不会显示为独立符号(用空格或其他分隔符分隔),因此不会替换为 -1。

FOO##PARAM 将在编译时展开,因此在运行代码之前,宏的值已修复,它是 FOOBAR,如果你添加一个新参数,如下所示:

#define FOOBAR 100
#define TEST(PARAM) FOO##PARAM
#define BAR -1
#define GOOD 10
int main(){
    cout<<TEST(GOOD)<<endl; 
}

编译器可能永远不会让它为你工作。