布尔值的排序

22

在C++或C99的<stdbool.h>中,布尔值的小于运算符<如何定义?

或者,解释以下代码的行为:

#ifndef __cplusplus
#include <stdbool.h>
#endif
#include <stdio.h>

int main() {
    bool b = -1;
    if(b < true) {
        printf("b < true\n");
    }
    if(b < false) {
        printf("b < false\n");
    }
    if(true < false) {
        printf("true < false\n");
    }
    if(false < true) {
        printf("false < true\n");
    }
}
在 MSVC 版本 10 下,编译为 C++ 代码时,在 Ubuntu5 编译的 GCC 4.6.3 编译为 C 代码以及在 Ubuntu5 编译的 G++ 4.6.3 中编译为 C++ 代码,你只会得到:
false < true

也就是说,以下不等式都是false

(bool)-1 < true
(bool)-1 < false
true < false

以下内容true

false < true
7个回答

21
在C++(我猜在C语言中也是如此),bool类型的比较完全就像是false等于0true等于1一样。如果类型是bool,则除了truefalse之外,没有其他可能值。
当将bool与其他数字类型进行比较时,它将转换为int,再次将false转换为0,将true转换为1
编辑:在C ++和C99的stdbool.h中,布尔值也被强制为0(false)或1(true) - bool b = -1;b的值设置为1。由于1 < 11 < 0都是false,所以问题中的不等式是正确的。
编辑:(由James编辑)除了上述编辑实际上并不正确,至少对于C++来说是如此。一个bool没有一个值为0或1,它的值为falsetrue。只有当它被提升为int时,才会创建01的值。
正如Konrad所指出的那样,bool值没有比较。对于比较运算符,发生“通常算术转换”,这意味着操作数都进行了整形提升,这意味着bool转换为int(以及charshort... 或枚举)。
所有这些都相当技术性。实际上,您可以记住:false表示假,true表示真,或者您可以将false视为0,将true视为1,以适应您的需要。唯一需要记住的重要事情是,bool类型不能有其他值。

有趣的是,我认为bool的位模式并不是由标准规定的。例如,实现可以使用位模式0x550xAA,只要所有转换为整数类型都给出0和1,转换为bool始终给出适当的值等等,包括静态变量的零初始化。

最后注意一点:bool b = -1;b设置为-1 != 0(即true,而不是1)。但当然,在任何数字上下文中,true都将转换为1


你能在标准中找到这个定义吗?我刚刚查了一下,但没能找到它(我甚至不确定该搜索什么)。 - Konrad Rudolph
@Mansuro 不相关,James和我正在讨论C ++。但即使对于C,这个文档中也没有说明如何处理转换(bool) -1 - Konrad Rudolph
1
§4.5 整数提升。 "类型为bool的右值可以转换为类型为int的右值,其中false变为零,true变为一。"(请注意,bool永远不会有值为01的情况;只有falsetrue。这就是我说“就像”的原因。)而§4.12则用于转换为bool - James Kanze
是的,但它在哪里定义了它们的顺序?编辑:噢,算了。 - Konrad Rudolph
2
@KonradRudolph:bool类型没有实际排序。与许多其他操作一样,根据上述规则将其提升为int,然后比较两个int的值。 - David Rodríguez - dribeas
显示剩余2条评论

5
这很有道理。整型 => 布尔类型的转化实际上是 b = i != 0。为了进行 < 比较,它通过规则 false=>0 和 true=>1 将布尔类型提升为整型。在你的第一个情况中,-1 将被视为 true,并且两个值都会提升为 1,因此结果为 false。显然,在第二和第三个情况下,1 永远不会小于 0,而在最后一个情况中,0 < 1

3

布尔值似乎被定义为(带符号的)整数类型,false为0,zero为1。这就解释了为什么true > false(1 > 0)是true。

此外,将-1与无符号数字进行比较会将-1转换为无符号数,在您的平台上,这会导致整数溢出,导致UINT_MAX(或bool类型中的其他类型) 。现在可以解释为什么以下表达式是错误的:

((bool)-1) < true i. e. UINT_MAX < 1
((bool)-1) < false i. e. UINT_MAX < 0
true < false i. e. 1 < 0

1
严格来说,“bool”被定义为一种有符号(不是无符号)整型,尽管它可以取的唯一值(truefalse)都具有非负的值。当视为“int”类型时,而((bool)-1)并非UINT_MAX,而是1 - James Kanze
bool不是无符号整数,它被定义为int。http://gel.sourceforge.net/examples/stdbool_8h-source.php - Mansuro
在 C 语言中,_Bool(作为 bool 的底层类型)被定义为无符号整数类型。所有转换为 bool 的非零值都会得到值 1。因此 (bool)-1 总是等于 1,因此 < true< false 始终为假。 - Jens Gustedt
1
@JamesKanze:这就是那些假设C/C++“足够相似”的问题的问题所在。在C99中,_Bool(bool是扩展到_Bool的宏)的类型是无符号的。 - David Rodríguez - dribeas
@DavidRodríguez-dribeas 的观点非常到位!(在 Objective-C 中,有 typedef unsigned char BOOL; - user529758
@H2CO3:我没有,这里加上+1来弥补 :) - David Rodríguez - dribeas

2

操作符 > 和 < 基于以下内容:

true == (1)
false == (0)

因为在 bool b = -1; 中涉及到了“滚动算术”,所以以下表述是错误的: (bool)-1 < true (bool)-1 < false


2

对于C++来说,只需将false设置为小于true

对于C语言而言,回答会更加困难。我在我的stdbool.h中看到了typedef char _Bool; /* For C compilers without _Bool */

似乎,如果编译器支持_Bool,它的工作方式就像C++一样,并自动转换为0/1,但如果不支持,则应按char方式工作,这将是b < true,如果char被标记为有符号,则为b < false

对于我而言,在C甚至是(int)(bool) -1也等于1,所以bool的定义不是char


你的编译器似乎不符合 C99 或 C11 标准,如果它真的执行了这个 typedef_Bool 是一种无符号整数类型,可以保存值 01,所有与 0 不同的值都将转换为 1 ,例如 (bool)-1。(在使用 char 作为替代品时,后者不会正确工作。)由于这是一个整数类型,所以可能值的排序与所有整数类型相同,即 0 小于 1 - Jens Gustedt

2
布尔值的顺序是这样排列的,即 falsetrue 小。根据标准,bool 只能保存两个值:truefalse,所以在 (bool)-1 中进行的转换应该得到 true(因为所有非 0 值在转换为 bool 时都是 true)。这是 clang 和 g++-4.7 的行为。
实际比较(我认为)是在将 bool 提升后进行的 int 比较,而你测试的编译器似乎避免了通过 bool 进行中间转换的步骤,直接提升了实际的 bool 值。

1
这里有一个解释,虽然我还没有与标准进行核对。从你的实验来看,似乎布尔值没有定义"<"运算符。比较的是布尔值转换成的无符号整数。理论上讲,标准可能不能保证所有"true"布尔值被转换为相同的值。而-1则被转换为最大的无符号整数。
作为另一个实验,以下代码:
#include <iostream>

int main()
{
std::cout<< (((bool)1) == true) << "\n";
std::cout<< (((bool)2) == true) << "\n";
std::cout<< (((bool)0) == false) << "\n";
std::cout<< (((bool)1) == false) << "\n";
  return 0;
}

打印 1 1 1 0

因此,任何非零值都是“真”。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接