【问题标题】:Comparison of bool data types in C++C++中bool数据类型的比较
【发布时间】:2026-01-29 05:15:03
【问题描述】:

bool 数据类型通常表示为0false)和1true)。但是,有人说true 值可以用1 以外的值表示。如果后面的语句是true,那么下面的表达式可能不正确。

bool x = 1;
if (x==1)
    Do something..

我想知道以下语句是否可以在常用编译器上按预期工作。

  1.  

    bool x = 1;
    if (x==1)
        Do something.
    
  2.  

    bool y = 0;
    if (y>0.5)
        Do something..
    
  3.  

    bool z = 1;
    if(z>0.5)
        Do something...
    

【问题讨论】:

  • This implicit conversion reference 可能有助于阅读。
  • 根据布尔转换规则:“零值(对于整数、浮点和无范围枚举)和空指针和空指针到成员值变为假。所有其他值成为现实。”
  • bool 之间的转换不取决于bool 的表示方式。即使 true 表示为 39 并且 false 表示为 10003,您的代码也可以工作。
  • 我的直觉是这个问题背后有更深层次的东西。也许不是关于隐式转换,可以根据规范查找和争论,而是关于“实际表示”。也许在沿着double x = *(reinterpret_cast<double*>>(&someBool)); 的行的骇人听闻的扭曲过程中会发生什么(即当残酷地暴露实际表示时 - 不确定我脑海中的确切语法,或者它是否会在某些时候导致 UB ......)
  • FWIW,看起来this paper 很可能会进入标准,此时 0 和 1 将是唯一允许的真假表示。

标签: c++ implicit-conversion


【解决方案1】:

C++ standard 的§4.5 说:

bool 类型的右值可以是 转换为 int 类型的右值, 假变成零和真 合而为一。

关于 2 和 3,发生类型转换,因此语句将按需要工作

【讨论】:

  • 这句话出自哪里?
  • @Brian:C++ 由 ISO 标准 (14882) 正式记录。因此,在 Stack Overflow 上,这些省略源文档的引用被假定为引用 then-current C++ 标准。由于这是 2019 年的答案,这意味着引用来自 ISO 14882:2017(又名 C++17)。
  • @MSalters 我知道事实并非来自 ISO 14882:2017。
  • 我怀疑它来自 C++03 标准,但我没有方便检查的副本。
  • 此文本仅指定转换的作用,而不是应用转换的时间。 OP 的一些示例将 bool 转换为 float,而不是将 bool 转换为 int。每个运算符的规范都指定了适用于该情况的转换。
【解决方案2】:

根据Boolean conversions的规则:

整数、浮点、无范围枚举、指针的纯右值, 和指向成员类型的指针可以转换为类型的纯右值 bool.

零值(用于整数、浮点和无作用域 枚举)和空指针和指向成员的空指针 值变为false。所有其他值变为true

然后

bool x = 1; // x will be true
bool y = 0; // y will be false
bool z = 1; // z will be true

对于第一种情况,if (x==1)x 将是 promotedint

类型bool 可以转换为int,值false 变为​0​,true 变为1

那么(x==1) 就是true

对于第二种情况,if (y>0.5)y 将提升为 int,其值为 0,然后将 converted 提升为 double,用于 comparison

如果操作数具有算术或枚举类型(作用域或非作用域),则按照算术运算符的规则对两个操作数执行通常的算术转换。转换后比较值:

如果传递给算术运算符的操作数是整数或无范围枚举类型,则在任何其他操作之前(但在左值到右值转换后,如果适用),操作数会经历整数提升。

...

  • 否则,如果任一操作数为double,则另一操作数转换为double

那么y>0.5 就是false

对于第三种情况,if (z>0.5)z 将提升为 int,其值为 1,然后将 converted 提升为 double,用于 comparison;那么z>0.5 就是true

【讨论】:

  • "y 将被提升为值为 0 的 int" - 这是不正确的。 y 将转换为 double。正如您的引用所涵盖的“否则,如果任一操作数是 double,则另一个操作数将转换为 double”。 (> 不是算术运算符)。 z 也是如此
  • @M.M 不应该先进行整体推广吗?正如我所引用的“如果传递给算术运算符的操作数是整数......那么在任何其他操作之前......操作数会经历整数提升。”
  • > 不是算术运算符
  • @M.M 是的,但我认为the rule 是一样的。 “如果操作数具有算术或枚举类型(作用域或非作用域),则按照算术运算符的规则对两个操作数执行通常的算术转换。转换后比较值:”
  • 您在上一条评论中的引用是正确的,并且在您的回答中引用了“通常的算术转换”的行为,即“否则,如果任一操作数为双精度,则另一个操作数将转换为双精度”
【解决方案3】:

if (x==1) 没有错误。当您将布尔值转换为数值类型时,所有真值表示都会转换为 1。

给定bool z=trueif(z>0.5) 将为真,因为 1.0 大于 0.5。

【讨论】:

  • “不正确” - double negative
  • 即使可以进行强制转换,我认为我们不应该那样做。我们应该明确比较正确类型的变量,即使它更冗长。我看到了一些针对这些情况的编译错误
【解决方案4】:

bool只有两个值,分别是truefalse10 是整数文字,因此它们可以转换为 bool。您必须考虑转换在两个方向上都有效,但您不一定会返回相同的整数:

int a = 5;
bool b = a; // int -> bool conversion
int c = b;  // bool -> int conversion
std::cout << a << " " c;

打印:

5 1

0 之外的任何整数值都会转换为true,但true 始终会转换为1

记住这一点,您的所有示例都将按预期工作。但是,请注意bool 的主要目的是我们可以在代码中使用truefalse 而不必给数字赋予01 的特殊含义。明确一点总是更好,所以当你的意思是true时,你最好写true而不是1

【讨论】:

    【解决方案5】:

    这里的一个相关问题是“为什么我们甚至允许在 boolint 之间进行比较?”。

    答案是向后兼容和妥协,因为 C 和 C++ 过去推荐使用整数来存储布尔值。所以有很多代码

    1. 尽管有新的语言规则,仍应继续工作,例如 关系运算符返回 bool 而不是 int。
    2. 允许您通过更改布尔变量的声明来升级旧代码 对其余代码进行最少的后续更改。

    其他语言在这方面可能更简洁,但bool 类型显然是成功的。

    【讨论】: