c - 在#define 之前使用#undef

标签 c macros c-preprocessor

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

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

#undefine FORMULA 使用了什么? 我可能猜想它处理的是之前已经定义了宏的情况。但是新定义不是覆盖了旧定义吗?谢谢!

最佳答案

当前定义的宏名称不能用 不同的 定义重新定义(见下文),因此 #undef 允许用不同的定义重新定义该宏名称。

这是相关的法律术语:

C 和 C++ 标准(相同的措辞):

A macro definition lasts (independent of block structure) until a corresponding #undef directive is encountered or (if none is encountered) until the end of the preprocessing translation unit.

措辞略有不同,意思相同:

C Standard (N1256), §6.10.3/2:
An identifier currently defined as an object-like macro shall not be redefined by another #define preprocessing directive unless the second definition is an object-like macro definition and the two replacement lists are identical. Likewise, an identifier currently defined as a function-like macro shall not be redefined by another #define preprocessing directive unless the second definition is a function-like macro definition that has the same number and spelling of parameters, and the two replacement lists are identical.

C++ Standard (N3337) §16.3/2
An identifier currently defined as an object-like macro may be redefined by another #define preprocessing directive provided that the second definition is an object-like macro definition and the two replacement lists are identical, otherwise the program is ill-formed. Likewise, an identifier currently defined as a function-like macro may be redefined by another #define preprocessing directive provided that the second definition is a function-like macro definition that has the same number and spelling of parameters, and the two replacement lists are identical, otherwise the program is ill-formed.

两个标准中的措辞相同:

Two replacement lists are identical if and only if the preprocessing tokens in both have the same number, ordering, spelling, and white-space separation, where all white-space separations are considered identical.

所以:

#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 两个标题。没有警告,可能不是预期的结果。

关于c - 在#define 之前使用#undef,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28136208/

相关文章:

c++ - 如何做一个运行时子类化系统

c - 单元测试实际过程

c - 将 STDOUT 和 STDERR 重定向到文件 ">&"

function - 将java方法名称作为clojure中的函数arg

c++ - "__cplusplus"宏扩展成什么?

c - 如何通过宏向 C 库提供选项

c - 通过预处理器指令自扩展代码

c++ - pthread读写锁不起作用吗?

c - 平均函数的错误答案?

c++ - 是否可以制作一个用分号替换换行符的宏