为什么不带 undef 的宏重定义会导致程序格式错误

问题描述 投票:0回答:2

根据标准,在没有使用

#undef
之前,禁止宏重定义:

但以下重新定义无效:

#define OBJ_LIKE    (0)         // different token sequence
#define OBJ_LIKE    (1 - 1)     // different whitespace

同时允许

#undef
对于之前根本没有定义的宏:

如果指定的标识符当前未定义为宏名称,则会被忽略。

我很感兴趣这样做的理由是什么,即禁止在中间没有

#undef
的情况下重新定义?一些编译器优化目的还是什么?

c++ c-preprocessor language-design
2个回答
2
投票

这是不允许的,因为默默地重新定义宏以表示其他含义可能是一个错误。 考虑以下示例:

// in assertions.hpp
#define assert(expr, msg) if (!expr) std::cout << msg << '\n';
#include "assertions.hpp"
// ...
#include <cassert> // could be included directly or indirectly
// ...

int main() {
    // expected to fail and print "huh ?!" to std::cout
    assert(false, "huh ?!");
    // may expand to:
    // ((false, "huh ?!") ? void() : __fail("huh ?!"))
}

这个断言现在成功了,因为

assert
中的
<cassert>
重新定义了断言是什么。 一般来说,重新定义事物可能会产生多种后果:

  • 只会产生编译器错误
  • 默默地重新定义全局常量以具有不同的值
  • 默默地重新定义类似函数的宏以具有不同的行为

请记住,

#include
的顺序很重要,并且每个宏都可以通过这种方式溢出到任何其他标头中。 与宏重新定义相关的错误可能很难追踪。

如果您想重新调整宏名称的用途,您可以先

#undef
它。


0
投票

我们无法检查 MACRO 定义,我们只能检查 MACRO 是否定义。

因此,如果您想检查

#undef
是否仅在定义的宏上完成,您可以自己检查:

#ifdef MY_MACRO
# undef MY_MACRO
#else
# error "Expected previous definition"
#end

要重新定义MACRO,这是不可能的

#define MY_MACRO some_def

// #ifdef MY_MACRO // only check it is defined not its definition
                   // so cannot differentiate for below two cases

#define MY_MACRO some_def    // OK (same def)
#define MY_MACRO another_def // Invalid
© www.soinside.com 2019 - 2024. All rights reserved.