根据标准,在没有使用
#undef
之前,禁止宏重定义:
但以下重新定义无效:
#define OBJ_LIKE (0) // different token sequence #define OBJ_LIKE (1 - 1) // different whitespace
同时允许
#undef
对于之前根本没有定义的宏:
如果指定的标识符当前未定义为宏名称,则会被忽略。
我很感兴趣这样做的理由是什么,即禁止在中间没有
#undef
的情况下重新定义?一些编译器优化目的还是什么?
这是不允许的,因为默默地重新定义宏以表示其他含义可能是一个错误。 考虑以下示例:
// 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
它。
我们无法检查 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