【问题标题】:Broken multi line macro破碎的多行宏
【发布时间】:2019-12-19 03:38:22
【问题描述】:

当我将 Nilorea 库中的这个多行宏包含在我的 C++ 项目中时,它无法编译。它被标记为外部“C”。

尝试过 GodBolt,并且 GCC 8.1 编译器在以下代码中的 if 语句中出现问题:https://godbolt.org/z/Lq_7aT

#define Free( __ptr )\
    if (  __ptr  )\
    {\
        free(  __ptr  );\
        __ptr  = NULL;\
    }
int* i = 0;
Free(i);

它应该编译。这是使用标准的问题吗?

我用一个糟糕的可编译示例编辑了这个问题。

【问题讨论】:

  • 你说一个宏被标记为extern "C"是什么意思?这对 C 预处理器来说毫无意义!
  • 注意:下划线是为编译器保留的。我假设你在一个函数中调用你的Free(0)
  • 它定义的header标记为extern c
  • free(NULL) 没问题,if ( __ptr ) 测试用处不大。
  • 你知道你可以用-E开关在godbolt中运行编译器吗? godbolt.org/z/1Nyfvq 这将消除 macro 噪音。

标签: c macros


【解决方案1】:

Godbolt 代码无法编译,因为

  • 您在函数外部调用代码
  • 您正在尝试分配给文字 0
  • 您没有包含必要的标题。

此外,如 cmets 中所述,标识符中的双下划线保留用于实现。编译器不会对此进行诊断,但无论如何它都是非法的。

当解决这三个问题时,它可以工作:

#include <stdlib.h>

#define Free(ptr) \
    if (ptr) \
    { \
        free(ptr); \
        ptr = NULL; \
    }

int main(void) {
    int *px = NULL;
    Free(px);
}

(我还修复了糟糕的、不一致的间距。)

【讨论】:

  • @Toby 在定义中没有必要使用void
  • @KonradRudolph 就C标准的字母而言,是的,将(void)写成函数定义的参数列表是多余的。但是,我可以方便地测试的每个 C 编译器在函数定义和声明中都给参数 list() 赋予了“未指定数量的参数”的含义,因此无论如何编写它都是一种很好的风格。 (在 C++ 中,()(void) 是相同的。)
  • @BugSquasher,不是因为下划线,罪魁祸首就是这个0 = NULL;你不能给常量字面量赋值。
  • @BugSquasher 您的样本没有错,因为下划线(在 this 特定情况下不会导致问题),而是因为这个答案中提到的第 1 点和第 3 点.第 2 点已过时,因为您同时更改了代码。
  • @zwol 我确信 GCC 中的 -Wextra 处理了这个问题。不知道我是怎么想到的(但是,clang 8 确实标记了它)。
猜你喜欢
  • 1970-01-01
  • 2016-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-08-11
相关资源
最近更新 更多