cpp*_*ner 7 c++ language-lawyer c++20
考虑
#define VER 1
#undef VER
#define VER 2
#if defined(VER) // #1
#error VER is defined
#endif
Run Code Online (Sandbox Code Playgroud)
如果宏指令在该位置之前的翻译单元中具有定义点,并且在该位置之前的翻译单元中没有未定义点,则该宏指令在源位置处处于活动状态。
我的理解是在(the )之前VER有一个undefinition 点,因此它不被认为是active。也就是说,应该扩展到,并且该指令不应该生效。#1#undef VERdefined(VER)0#error
但在实践中,所有编译器都会产生一条错误消息VER is defined(这符合我的直觉,但不符合我对标准的理解)。
我的理解不正确吗?我错过了什么?
让我们看看我是否可以为此辩护。
上面链接指向的段落说:
- 在对程序中的每个翻译单元进行预处理时遇到的每个 #define 指令都会产生一个不同的宏定义。
所以,#define VER 1是一个定义,而且#define VER 2是一个不同的定义。
5.1 翻译单元中宏定义的定义点是其#define 指令出现的点
显然,两者都有一个定义点。
5.2 翻译单元内宏定义的取消定义点是在其定义点之后出现命名宏的#undef 指令的第一个点,[...]
并且#define VER 1有一个#define VER 2不确定的点,而没有。
因此,宏定义#define VER 2在测试位置是活动的。在某些较早的时间点,#define VER 1将改为活跃。
再说一次,如果你要这样做:
#define X 1
#define X 2
#undef X
/* is X active now ??? */
Run Code Online (Sandbox Code Playgroud)
第一个似乎没有“不确定点” #define,但我认为你会遇到
7 如果一个宏将被替换或重新定义,并且该宏名称有多个激活的宏定义,则激活的宏定义都应是同一宏的有效重新定义
因为它们不是同一个宏。(在cpp.replace页面中有示例。)虽然 GCC 和 Clang 接受了警告,但明显的语义是用新值重新定义它(而不是例如堆叠定义以便#undef只删除一个 - 那样说疯狂。)