31

在我正在编写的一些代码中,我遇到了对真假的奇怪重新定义。我以前见过这样的事情,以使检查更加严格/确定,但这在我看来有点奇怪,我想知道是否有人可以告诉我这样定义的充分理由,请参阅下面的我的评论他们旁边:

#define FALSE (1 != 1) // why not just define it as "false" or "0"?
#define TRUE (!FALSE)  // why not just define it as "true" or "1"?

这个代码库中还有许多其他奇怪的地方。就像所有标准类型都有重新定义一样:

#define myUInt32 unsigned integer // why not just use uint32_t from stdint?

所有这些小“怪癖”让我觉得我错过了一些明显的东西,但我真的看不出重点:(

注意:严格来说,这是 c++ 代码,但它可能是从“c”项目中移植的。

4

7 回答 7

35

目的似乎是可移植性

#define FALSE (1 != 1) // why not just define it as "false" or "0"?
#define TRUE (!FALSE)  // why not just define it as "true" or "1"?

这些在支持它的语言中具有布尔类型(C++),同时为那些不支持它的语言提供仍然有用的数值(C——甚至 C99 和 C11,显然,尽管它们获得了显式的布尔数据类型)。

尽可能使用布尔值有利于函数重载。

#define myUInt32 unsigned integer // why not just use uint32_t from stdint?

stdint如果有空就好了。你可能认为这样的事情是理所当然的,但那里是一个广阔的世界!这段代码承认这一点。

免责声明:就个人而言,我坚持这些标准,并简单地声明 1990 年以后发布的编译器是先决条件。但我们不知道所讨论项目的基本要求是什么。

TRWTF 是有问题的代码的作者没有在旁边的评论中解释这一点。

于 2013-10-14T11:43:31.073 回答
11
#define FALSE (1 != 1) // why not just define it as "false" or "0"?

我认为这是因为表达式的类型(1!=1)取决于语言对布尔值的支持——如果是 C++,则类型为bool,否则为int

另一方面,在两种语言0中总是int,并且false在 C 中不被识别。

于 2013-10-14T11:43:44.530 回答
7

严格来说,这是 c++ 代码,但它可能是从“c”项目中移植过来的。

这与前面提到的可移植性有关,但实际上远不止于此。这是对语言定义的巧妙利用,以符合语言

这些看起来很荒谬的宏并不像乍一看那么荒谬,但它们实际上很巧妙,因为它们保证 C 和 C++TRUEFALSE具有正确的值(和类型)truefalse(即使编译器是 C没有这些关键字的编译器,所以你不能随便写一些类似的东西#define TRUE true)。

在 C++ 代码中,这样的结构是没有用的,因为语言将true和定义false为关键字。
但是,为了使 C 和 C++ 在同一代码库中无缝互操作,您需要对两者都有效的“东西”(除非您想使用不同的代码风格)。

这些宏的定义方式证明了 C++ 标准明确模糊了哪些值truefalse实际具有哪些值。C++ 标准规定:

bool 类型的值为真或假。
[...]
零值、空指针值或空成员指针值被转换为 false;任何其他值都将转换为 true。
[...]
bool 类型的纯右值可以转换为 int 类型的纯右值,false 变为 0,true 变为 1。

请注意它是如何说存在两个特定值的,它们的名称是什么,以及它们转换成和从什么对应的整数值,但它没有说明这些值是什么。您可能倾向于认为这些值显然是01顺便说一句,您可能猜对了),但事实并非如此。故意未定义实际值。

这类似于指针(尤其是空指针)的定义方式。请记住,零的整数文字转换为空指针,而空指针转换为false,比较相等...等等等等。
关于哪个转换为什么和什么等等的说法很多,但事实并非如此在任何地方说空指针必须具有零的二进制表示(事实上,存在一些奇特的架构,但情况并非如此!)。

于 2013-10-14T12:26:45.340 回答
6

其中很多有历史原因,例如从 C 迁移的旧代码、来自非标准 C++ 编译器的代码、交叉编译器代码(可移植性)、支持向后兼容、遵循代码样式、不良习惯。

有一些编译器不<cstdint>支持整数类型uint32_t,或者他们没有<cstdbool>。一个好的程序员必须定义一切并大量使用预处理器,以使他的程序在不同的编译器上得到很好的定义。

今天,我们可以使用<cstdint>, true/false, <cstdbool>, ... 并且每个人都很开心!

于 2013-10-14T11:43:57.297 回答
5

这个定义的好处是避免了从 TRUE 或 FALSE 到整数的隐式转换。这对于确保编译器不会选择错误的函数重载很有用。

于 2013-10-14T11:43:43.387 回答
4

C 没有本机布尔类型,因此您不能严格使用“false”或“true”而不在其他地方定义它们——那么您将如何定义呢?

相同的论点适用于 myUInt32 - C 最初没有 uint32_t 和 stdint 中的其他类型,因此这提供了一种确保您获得正确大小整数的方法。如果您移植到不同的体系结构,您只需将 myUInt32 的定义更改为等于 32 位宽的无符号整数 - 无论是长整数还是短整数。

于 2013-10-14T11:44:41.020 回答
1

有一个很好的解释说明了 false 和 FALSE 之间的区别。我认为这可能有助于进一步理解,尽管大多数答案都已经解释过了。 这里

于 2013-10-14T11:54:30.297 回答