【问题标题】:Ordering of boolean values布尔值的排序
【发布时间】:2012-08-10 17:03:46
【问题描述】:

在 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++代码,GCC 4.6.3-ubuntu5编译为C代码,G++ 4.6.3-1ubuntu5编译为C++代码,你得到的只是

false < true

即以下不等式都是false

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

以下是true

false < true

【问题讨论】:

    标签: c++ c boolean comparison-operators


    【解决方案1】:

    在 C++ 中(我也怀疑在 C 中),bools 比较就像 false0true1。如果类型是bool,则没有 truefalse 以外的值是可能的。

    bool与其他数值类型比较时,会转换为int, 再次将false 转换为0true 转换为1

    编辑: C99 中的 C++ 和 stdbool.h 都强制布尔值为 0(假)或 1(真) - bool b = -1;b 的值设置为 1。由于1 &lt; 11 &lt; 0 都是假的,所以问题中的不等式是正确的。

    编辑:(詹姆斯)除了上面的编辑不是真的正确,在 至少对于 C++。 bool 没有值 0 或 1,它有一个值 falsetrue。只有当它被提升为int 时 转换会创建 01 的值。

    正如 Konrad 指出的那样,bool 值没有可比性。 比较运算符会发生“通常的算术转换”, 这意味着对两个操作数的积分提升,这意味着 bool 转换为 intcharshort... 或枚举也是如此)。

    所有这些都是相当技术性的。在实践中,你可以记住 false true,或者你可以认为false是0,true是1, 哪个最适合您。唯一要记住的重要事情是 bool 可以有 no 其他值。

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

    最后一点:bool b = -1;b 设置为 -1 != 0(即 true,不是1,但当然,true 将转换为1 数字上下文。

    【讨论】:

    • 你能找到标准中的定义吗?我只是看了看,找不到(我什至不确定要搜索什么)。
    • @Mansuro Irrelevant,James 和我在谈论 C++。但即使对于 C,本文档中也没有说明如何处理转换 (bool) -1
    • §4.5 整体促销。 “bool 类型的右值可以转换为int 类型的右值,false 变为 0,true 变为 1。” (请注意,bool 永远不会有 01 的值;只有 falsetrue。这就是为什么我说“完全好像。”)和§4.12转换为bool
    • 是的,但是它在哪里定义了它们的顺序?编辑:呃,算了。
    • @KonradRudolph:bool 上没有实际订购。与许多其他操作一样,根据上述规则将值提升为int,然后比较两个整数。
    【解决方案2】:

    这很有意义。整数类型 => bool 转换实际上是b = i != 0。为了进行&lt; 比较,它通过规则 false=>0 和 true=>1 将 bool 提升为 int。在您的第一种情况下,-1 将等同于 true,并且两者都将提升为 1,因此它是 false。显然,对于第二种和第三种情况,1 永远不会小于 0,而在最后一种情况下,0 &lt; 1

    【讨论】:

      【解决方案3】:

      operator > 和

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

      这个错误: (布尔)-1

      【讨论】:

        【解决方案4】:

        对于 C++,只需 false true

        因为 C 更难回答。我明白了

        typedef char _Bool; /* For C compilers without _Bool */ 在我的 stdbool.h 中

        似乎,如果编译器支持 _Bool ,它就像在 C++ 中一样工作并自动转换为 0/1,但如果不是,它应该作为 char 工作,如果 char 被签名,它将是 b &lt; trueb &lt; false

        对我来说 (int)(bool) -1 即使在 C 中也是 1,所以 bool 被定义为非字符

        【讨论】:

        • 如果你的编译器真的这样做typedef,它似乎不符合 C99 或 C11。 _Bool 是一个无符号整数类型,它可以保存值 01,并且所有不同于 0 的值都将转换为 1,例如 (bool)-1。 (后者不能与 char 一起正常工作。)由于这是一个整数类型,因此可能值的顺序与所有整数类型相同,0 小于 1
        【解决方案5】:

        布尔值的排序使得false 小于true。根据标准,bool 只能包含两个值:truefalse,因此(bool)-1 中的转换应该产生true(因为所有非0 值转换为bool 时都是@987654328 @)。这就是 clang 和 g++-4.7 中的行为。

        实际比较(我相信)是在提升bool 之后在int 上完成的,并且您测试的编译器似乎避免了通过bool 转换的中间步骤,而只是提升了实际的bool 值。

        【讨论】:

          【解决方案6】:

          bool 似乎被定义为一个(有符号的)整数类型,false 为 0,0 为 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
          

          【讨论】:

          • 正式地,bool 被定义为有符号(非无符号)整数类型,即使它可以采用的唯一值(truefalse)都具有非负值。而((bool)-1) 不是UINT_MAX,当被视为int 时,它是1
          • bool 不是 unsigned int,它被定义为 int gel.sourceforge.net/examples/stdbool_8h-source.php
          • 在 C 中 _Bool(作为 bool 后面的底层类型)被定义为无符号整数类型。所有与0 不同的值转换为bool 的结果为1。所以(bool)-1 总是1,因此&lt; true&lt; false 总是假的。
          • @JamesKanze:这就是关于 C/C++ 的问题的问题,假设它们足够相似。在 C99 中,_Boolbool 是扩展为 _Bool 的宏)的类型是无符号的。
          • @DavidRodríguez-dribeas 完美点! (在Objective-C中,有typedef unsigned char BOOL;
          【解决方案7】:

          这是一个解释,不过我还没有检查过标准。 从您的实验看来,“

          作为另一个实验,下面的代码

          #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

          所以任何非零值都是“真”。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-04-02
            • 1970-01-01
            • 1970-01-01
            • 2016-02-20
            • 2012-09-24
            • 1970-01-01
            相关资源
            最近更新 更多