在#define之前使用#undef

时间:2015-01-25 12:09:16

标签: c macros c-preprocessor

在许多地方,我在定义相同的宏之前看到了undefine宏的用法。例如:

#undef FORMULA
#ifdef SOMETHING
#define FORMULA 1
#else 
#define FORMULA 2
#endif

#undefine FORMULA使用了什么? 我可能猜测它处理之前已定义宏的情况。但新的定义是否超越旧定义?谢谢!

4 个答案:

答案 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 ++语言规范不允许这样做。这样做是不便携的。