真正的问题是定义是由与语言的其余部分(预处理器)不同的工具处理的。结果,编译器对此一无所知,并且在出现问题时无法帮助您——例如重用预处理器名称。
考虑max
有时将其实现为宏的情况。因此,您不能max
在代码中的任何地方使用标识符。任何地方。但是编译器不会告诉你。相反,你的代码会出错,你不知道为什么。
现在,只要小心一点,这个问题就可以最小化(如果不能完全消除的话)。但是对于大多数用途#define
来说,无论如何都有更好的选择,因此成本/收益计算变得有偏差:没有任何好处的轻微劣势。为什么在没有优势的情况下使用有缺陷的功能?
所以这是一个非常简单的图表:
- 需要常数吗?使用常量(不是定义)
- 需要功能吗?使用函数(不是定义)
- 需要无法使用常量或函数建模的东西?使用定义,但要正确执行。
“正确地”做这件事本身就是一门艺术,但有一些简单的指导方针:
使用唯一的名称。所有大写字母,始终以唯一的库标识符作为前缀。max
? 出去。VERSION
? 出去。相反,使用MY_COOL_LIBRARY_MAX
和MY_COOL_LIBRARY_VERSION
。例如,Boost 库,宏的大用户,总是使用以BOOST_<LIBRARY_NAME>_
.
小心评价。实际上,宏中的参数只是被替换的文本。结果,#define MY_LIB_MULTIPLY(x) x * x
被破坏:它可以用作MY_LIB_MULTIPLY(2 + 5)
,导致2 + 5 * 2 + 5
. 不是我们想要的。为了防止这种情况发生,请始终将论点的所有用途括起来(除非您确切地知道自己在做什么——剧透:您可能不知道;即使是专家也经常会犯这种错误,令人震惊)。
这个宏的正确版本是:
#define MY_LIB_MULTIPLY(x) ((x) * (x))
但是仍然有很多方法可以让宏严重错误,而且,重申一下,编译器在这里帮不了你。