在许多地方,我在定义相同的宏之前看到了undefine宏的用法。例如:
#undef FORMULA
#ifdef SOMETHING
#define FORMULA 1
#else
#define FORMULA 2
#endif
#undefine FORMULA
使用了什么?
我可能猜测它处理之前已定义宏的情况。但新的定义是否超越旧定义?谢谢!
答案 0 :(得分:5)
当前定义的宏名称无法使用不同的定义重新定义(请参见下文),因此#undef
允许使用不同的定义重新定义宏名称。
以下是相关的法律术语:
C和C ++标准(相同的措辞):
宏定义持续(独立于块结构),直到遇到相应的 #undef 指令或(如果没有遇到)指令,直到预处理转换单元结束。
措辞略有不同,含义相同:
C标准(N1256),§6.10.3/ 2:
当前定义为类似对象的宏的标识符不应由另一个 #define 预处理指令重新定义,除非第二个定义是类似于对象的宏定义且两个替换列表相同。同样,当前定义为类似函数宏的标识符不应由另一个 #define 预处理指令重新定义,除非第二个定义是具有相同数量和参数拼写的类函数宏定义,两个替换列表完全相同。C ++标准(N3337)§16.3/ 2
当前定义为类似对象的宏的标识符可以由另一个 #define 预处理指令重新定义,前提是第二个定义是类似于对象的宏定义并且两个替换列表相同,否则程序是病态的。同样,当前定义为类似函数的宏的标识符可以由另一个 #define 预处理指令重新定义,前提是第二个定义是类似函数的宏定义,其参数的数量和拼写相同,并且两个替换列表是相同的,否则程序是不正确的。
两个标准中的措辞相同:
当且仅当两者中的预处理标记具有相同的数字,排序,拼写和空白分隔时,两个替换列表是相同的,其中所有空白分隔都被认为是相同的。
所以:
#define X(y) (y+1)
#define X(z) (z+1) // ill-formed, not identical
恕我直言,由于预处理器宏的范围规则,使用#undef
通常很危险。我更喜欢从预处理器获得警告或错误,并提出一个不同的预处理器宏,而不是让一些翻译单元默默地接受一个错误的宏定义,这会在程序中引入一个错误。考虑:
// header1.h
#undef PORT_TO_WRITE_TO
#define PORT_TO_WRITE_TO 0x400
// header2.h
#undef PORT_TO_WRITE_TO
#define PORT_TO_WRITE_TO 0x410
并且有两个标题的翻译单元#include
。没有警告,可能不是预期的结果。
答案 1 :(得分:4)
是的,新定义会覆盖以前的所有内容。但是有相应的警告信息。使用#undef
,您没有任何警告。
答案 2 :(得分:0)
但新定义是否会覆盖旧定义?
是的,确实如此(当您的编译器允许时)。但是,重新定义宏会导致编译器警告,使用#undefine
可以避免。
这对编程商店有严格的编译器警告规则很重要 - 例如,要求所有生产代码都使用-Werror
标志编译,将所有警告视为错误。
答案 3 :(得分:0)
#undef
删除宏,因此可以再次定义名称。
如果宏从未在第一时间定义,#undef
没有效果,那么没有任何缺点。 #undef
... #define
应该被理解为替换任何可能的先前定义,但不是暗示它必须已经定义。
热门编译器允许您跳过#undef
,但官方标准ISO C和C ++语言规范不允许这样做。这样做是不便携的。