Skip to content

4.9 - 布尔值

Key Takeaway
  • 不能用括号初始化和一个整型数来初始化布尔变量,其他情况是可以转换的
  • std::cin 不能接收true或者false,除非使用 std::cout << std::boolalpha;

在现实中,有些问题的答案只有”是“或”不是“两种。”苹果是水果吗?“,是的。”你爱吃笋吗?“不。

现在,我们考虑一个类似的语句,它只能用truefalse来回答:”苹果是水果“,true。”我喜欢吃笋“,false

像这种只有两种可能答案的语句(yes/true 或 no/false)很常见,很多编程语言都有用于处理此类输出结果的特殊类型。它们称为布尔类型(注意:Boolean在英语中是大大写字母开头的,因为它的发明人是乔治布尔(George Boole))。

布尔变量

布尔变量只有两种可能的值:true 和 false

声明布尔类型的变量需要使用关键字 bool

1
bool b;

初始化布尔类型的变量或为其赋值,需要使用 true 或 false

1
2
3
4
bool b1 { true };
bool b2 { false };
b1 = false;
bool b3 {}; // 默认初始化为 false

和一元负号运算符(-)可以被用来将一个正数变成负数一样,使用逻辑运算符(!)可以将布尔值true变成false或者把false变成true

1
2
bool b1 { !true }; // b1 被初始化为 false
bool b2 { !false }; // b2 被初始化为 true

布尔值通常并不会以 “true” 或 “false”来存储。实际上它是以整型来存储的:true会变成1,false会变成0。类似地,当布尔类型求值时,求值的实际结果也并不是“true” 或 “false”。通常它们会求值成_0_ (false) 或 1 (true)。因为布尔类型实际上是以整型存储的,因此它属于一种整形的类型(integral type)。

打印布尔变量

当使用 std::cout打印布尔变量时, std::cout 会将 false 打印成 0,而把 true 打印成1:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
#include <iostream>

int main()
{
    std::cout << true << '\n'; // true evaluates to 1
    std::cout << !true << '\n'; // !true evaluates to 0

    bool b{false};
    std::cout << b << '\n'; // b is false, which evaluates to 0
    std::cout << !b << '\n'; // !b is true, which evaluates to 1
    return 0;
}

Outputs:

1
2
3
4
1
0
0
1

如果你希望 std::cout 打印 “true” 或 “false” 而不是 0 或 1,你可以使用 std::boolalpha。例如:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
#include <iostream>

int main()
{
    std::cout << true << '\n';
    std::cout << false << '\n';

    std::cout << std::boolalpha; // print bools as true or false

    std::cout << true << '\n';
    std::cout << false << '\n';
    return 0;
}

打印结果:

1
2
3
4
1
0
true
false

你可以使用 std::noboolalpha 来关闭此功能。

整型转换为布尔类型

你不能用括号初始化和一个整型数来初始化布尔变量:

1
2
3
4
5
6
7
8
9
#include <iostream>

int main()
{
    bool b{ 4 }; // 错误:: 不允许缩窄转换
    std::cout << b;

    return 0;
}

(注意:有些版本的g++并不会有上述限制)

不过,在其他场景下整型是可以被转换为布尔值的。整型值0会被转换为false,而其他整型会被转换为true

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
#include <iostream>

int main()
{
    std::cout << std::boolalpha; // print bools as true or false

    bool b1 = 4 ; // 拷贝初始化允许隐式转换
    std::cout << b1 << '\n';

    bool b2 = 0 ; // 拷贝初始化允许隐式转换
    std::cout << b2 << '\n';


    return 0;
}

打印结果为:

1
2
true
false

注意:bool b1 = 4; 可以能会产生警告。这种情况下你需要关闭编译的”将告警当做错误处理“功能,这样你猜呢编译上述代码。

输入布尔值

使用 std::cin 来输入布尔类型常常会让新手程序员抓狂。

考虑下面的程序:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
#include <iostream>

int main()
{
    bool b{}; // 默认初始化为 false
    std::cout << "Enter a boolean value: ";
    std::cin >> b;
    std::cout << "You entered: " << b << '\n';

    return 0;
}
1
2
Enter a Boolean value: true
You entered: 0

什么!怎么会这样?

实际上,std::cin只能够接收两种布尔类型输入:0和1(而不是 truefalse )。任何其他的输入都会导致 std::cin 出错。在上面的例子中,因为我们输入了true,因此实际上 std::cin出错了,输入出错后,接受输入的变量会被清零,因此b就被赋值为false。因此,当 std::cout 打印b的时候,会打印0。

为了让 std::cin 能够接受 “false” 和 “true” 作为输入,std::boolalpha 必须被打开。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
#include <iostream>

int main()
{
    bool b{};
    std::cout << "Enter a boolean value: ";

    // 允许用户输入 'true' 或 'false' 作为布尔值
    std::cin >> std::boolalpha;
    std::cin >> b;

    std::cout << "You entered: " << b << '\n';

    return 0;
}

不过,当std::boolalpha 打卡后,“0” 和 “1” 就不会再被看出布尔类型了。

布尔类型的返回值

布尔值常备用作函数的返回值,用来检查某件事(物)是否为true。这种函数命名时通常以is开头(例如 isEqual)或 has(例如 hasCommonDivisor)。

考虑下面这个例子,和上面有些类似:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <iostream>

// 如果 x 和 y 相等则返回 true 否则返回 false
bool isEqual(int x, int y)
{
    return (x == y); //  如果 x 和 y 相等,operator== 则返回 true 否则返回 false
}

int main()
{
    std::cout << "Enter an integer: ";
    int x{};
    std::cin >> x;

    std::cout << "Enter another integer: ";
    int y{};
    std::cin >> y;

    std::cout << std::boolalpha; // print bools as true or false

    std::cout << x << " and " << y << " are equal? ";
    std::cout << isEqual(x, y); // will return true or false

    return 0;
}

两次运行的输出结果如下:

1
2
3
Enter an integer: 5
Enter another integer: 5
5 and 5 are equal? true
1
2
3
Enter an integer: 6
Enter another integer: 4
6 and 4 are equal? false

原理是什么呢?首先我们从输入获取 x 和 y 的值。接下来,表达式 isEqual(x, y)会进行求值。在第一次运行时,执行的函数相当于 isEqual(5, 5)。在函数中,5 == 5被求值,得到的结果是 true。随后 true 被返回给主调函数并通过 std::cout 被打印出来。在第二次运行时,调用的函数相当于 isEqual(6, 4) ,返回的结果为 false

使用布尔值需要熟悉一下,不过当你习惯之后,会非常喜欢它表现出来的简洁!布尔值也是编程中非常大的一部分——你使用布尔值的情况比其他基本类型加起来都多。

我们会在下一节课中继续讨论布尔值。