FALSE和TRUE的奇怪定义,为什么?

时间:2013-10-14 11:39:03

标签: c++ c boolean

在我正在研究的一些代码中,我遇到了对真相和虚假的奇怪重新定义。我之前已经看过这样的事情,以便更加严格/确定地进行检查,但是这一点在我的脑海中有点奇怪,我想知道是否有人可以告诉我这些定义的原因是什么,请参阅下面我的评论旁边:

#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'项目移植。

7 个答案:

答案 0 :(得分:34)

意图似乎是可移植性

#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,显然,尽管它们获取了显式的布尔数据类型)。 p>

尽可能使用布尔值有助于功能超载。

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

如果stdint可用,那很好。你可以把这些事情视为理所当然,但这是一个广阔的世界!此代码识别出这一点。

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

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

答案 1 :(得分:11)

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

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

另一方面,0始终为int,在两种语言中都有false,但在C中无法识别。{/ p>

答案 2 :(得分:7)

  

严格来说这是c ++代码,但它可以从'c'项目移植。

这是关于如前所述的可移植性,但它实际上远远超出了。它是语言定义的巧妙利用,以符合语言

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

在C ++代码中,这样的构造将毫无用处,因为该语言将truefalse定义为关键字。
但是,为了使C和C ++在相同的代码库中无缝地互操作,您需要“适用于两者的东西”(除非您想使用不同的代码样式)。

这些宏的定义方式是C ++标准的证明,它明确含糊truefalse实际具有的值。 C ++标准规定:

  

bool类型的值为true或false   [...]
  零值,空指针值或空成员指针值转换为false;任何其他值都转换为true   [...]
  bool类型的prvalue可以转换为int类型的prvalue,false变为零,true变为1。

请注意它是如何表示存在两个特定值以及它们的名称是什么,以及它们转换为哪些相应的整数值,但并未说明这些值是什么。您可能倾向于认为值显然是01(并且您可能已经猜到了 ),但事实并非如此。故意没有定义实际值。

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

答案 3 :(得分:6)

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

有些编译器对<cstdint>等整数类型没有uint32_t,或者没有<cstdbool>。一个优秀的程序员必须定义所有内容并大量使用预处理器,以便在不同的编译器上很好地定义他的程序。

今天,我们可以使用<cstdint>true/false<cstdbool>,......每个人都很高兴!

答案 4 :(得分:5)

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

答案 5 :(得分:4)

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

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

答案 6 :(得分:1)

有一个很好的解释说明了false和FALSE之间的区别。虽然大多数答案已经解释过,但我认为它可能有助于进一步理解。 here