阅读关于预处理器的章节,它指出只有重新定义符合先前的定义时才允许重新定义宏,即:
#define FOO 0
#define BAR 1+1
#define FOO 0 /* ok. */
#define BAR 1 + 1 /* not ok */
我对此感到困惑。
当然这种行为是正确的(当然这本书可能是错的),我的问题是:为什么要允许这个?我想不出任何可以使用它的合法用例(授予我没有经验),它背后是否有理性?
答案 0 :(得分:2)
我们的想法是让预处理器主动观察重复的定义并确保它们保持一致。
实际上提到了这条规则背后的基本原理委员会希望不允许“恶毒的重新定义”,例如
(在header1.h中)
#define NBUFS 10
(在header2.h中)
#define NBUFS 12
这显然是对程序中严重错误的邀请。然而,仍然存在“良性重新定义”的问题,例如
(在header1.h中)
#define NULL_DEV / *第一次* / 0
(在header2.h中)
#define NULL_DEV / *第二次* / 0
C89委员会的结论是,通过允许在定义相同的情况下进行良性重新定义,可以更好地实现安全编程实践。这允许独立标题指定他们对每个感兴趣符号的正确值的理解,仅在定义不同时才生成诊断。
基本上,当两个定义存在且它们不同时,我们的想法是故意捕捉和暴露情境。如果用户在定义自己的定义之前总是被迫预测和#undef
之前的定义,他们会悄悄地覆盖不打算覆盖的内容,而无法确保一致性。
通过故意提供额外相同的定义,您可以有效地引入额外的保护级别:如果某人修改了之前的定义,预处理器将立即捕获并报告由此产生的不匹配。
换句话说,通过定义
#define A 42
在您的代码中,您不仅要将A
定义为42
,还要告诉预处理器您要确保其他所有人(在此翻译单元中)共享同一个概念{ {1}}应该是。
答案 1 :(得分:1)
你的书是完全正确的,但也许没有指出 - 或者你可能忽略了它 - 您可以重新定义先前定义的预处理器,但不提供诊断 在重新定义它之前你取消它。 E.g:
#define FOO 0
#define BAR 1+1
#define FOO 0 /* ok. */
#undef BAR
#define BAR 1 + 1 /* ok */
如果您在 定义时尝试重新定义宏,则概率很高 你犯了一个大错,并且会对预处理器感激不尽 请你注意。
在文件中定义一个宏,这个宏驻留在一个大而复杂的文件中 产品代码库 - 可能具有多个交织在一起的构建配置 由最终在代码库外定义的宏控制, 在构建系统中 - 然后知道这可能超出你的独立智慧 你的定义永远不会,灾难性地与建立任何一个的先前定义相矛盾 组态。你想知道这一点,预处理器会告诉你。
另一方面,有些情况下你想说:FOO
可能或
可能没有从我的某个地方获得事先的定义
文件已编译。无论如何,我希望它现在有我的定义。
我知道我在做什么,而且在我的脑海中。预处理器可以让你想到这一点
责任如下:
<强> foo.c的强>
#include <bar.h>
...
#undef FOO // I don't care what it previously might have been.
#define FOO what I want here
并保持安静。
从这个角度来看,为什么预处理器不抱怨的问题
可能是宏重新定义与最后一个没有区别
驱散。相同的重新定义是无害的。没用,是的,但不是
必然暗示你或任何人都重复了自己。图书馆
标头文件libfoo.h
和libbar.h
可能都包含在baz.c
和。{1}}中
他们每个人都可能包含。
#define MAX_HANDLES 255
预处理器将看到两次。但这是无害的,为什么要抱怨?