Skip to main content

Booleans

The bool type

If you recall from the Variables lesson, one of basic types listed was bool. This type represents a boolean, which is a single true/false value.

The Boolean Expressions we learned about early in this Conditions lesson create a boolean value when evaluated. So, we can make variables that are the results of such boolean expressions, and then further use these bool variables in the conditions of if statements.

C++ provides two built-in bool constants - true and false. You can use these wherever a bool or boolean expression is expected. For example:

Boolean literals
bool var1 = true;
bool var2 = false;

There are more interesting things we can do with bool variables, too. Any boolean expression is valid to assign here. Combining this with if statements can make for shorter and more readable code in some cases.

Using boolean variables to determine the weather
std::string name;

std::cout << "Enter your first name: ";
std::cin >> name;

// User is lucky if their name has more than 5 characters
bool is_lucky = name.size() > 5;

// Try changing these values yourself and see what happens!
bool is_tuesday = true;
bool is_cloudy = false;

std::string weather = "sunny";

if (not is_tuesday and is_cloudy) {
weather = "raining";
} else if (is_tuesday) {
if (is_cloudy) {
weather = "overcast";
} else if (not is_lucky) {
weather = "downpouring";
}
}

std::cout << "It is currently " << weather << " in your location!";

The logical operators previously introduced can also be used to create new boolean variables.

Using logical operators on bools
bool is_precipitating = weather == "raining" or weather == "downpouring";
bool is_rainbow_made = is_precipitating and not is_cloudy;
bool is_boring_day = not is_rainbow_made;

Input/Output with bool

If you did any self-driven exploration with this new bool type, you may have noticed a peculiar thing... Printing out a bool does not display a true or false in the terminal. Instead, it prints out a 1 or a 0. This is simply a default behavior in C++ that is related to the next section.

You can easily change this behavior by changing one of std::cout's settings. Simply "print" out the std::boolalhpa built-in constant, and it will make all future boolean operations on std::cout print out true/false instead of 1/0.

Header include

Make sure you #include <iomanip> to use std::boolalpha.

Printing true/false
std::cout << true << " " << false << "\n";
std::cout << std::boolalpha;
std::cout << true << " " << false << "\n";
Output
1 0
true false

Conversely, std::cin by default will only accept a 0 or a 1 when inputting into a bool variable. This behavior can also be changed by "inputting" into the std::boolalpha flag. In the example below, the user will first input 0, which represents false. Then, they will input true once the std::boolalpha setting was applied.

Inputting true/false
bool var;

std::cout << "Integral form: ";
std::cin >> var;

std::cin >> std::boolalpha;

std::cout << "Alphanumeric form: ";
std::cin >> var;
Input/Output
Integral form: 1
Alphanumeric form: true

As an exercise, try modifying the weather example from above to accept user input, using the std::boolalpha modifier you just learned.

Fun Fact

The name "boolalpha" comes from a portmanteau of boolean and alphanumeric.

intbool conversions

C++ has another rather annoying behavior where booleans and integers can implicitly convert between each other. A boolean value of false is equivalent to an integer value of 0, and true is equivalent to 1. Conversely, an integral value of 0 is equivalent to a boolean value of false, and any non-zero integer is equivalent to true.

A sampling of int↔bool conversions
int x = true; // x is 1
int y = false; // y is 0

bool a = 1; // a is true
bool b = 25; // b is true
bool c = -194; // c is true
bool d = 0; // d is false

While this behavior may seem neat, it can unexpectedly crop up in many places where they are not wanted. For this reason, if you want to intentionally trigger an intbool conversion, then you should cast the value.

Performing a cast
int x = static_cast<int>(true); // Modern-style cast
int y = (int) false; // C-style cast

bool a = static_cast<bool>(1);
bool b = (bool) 0;

There are two primary ways to perform a cast like this in C++ - a "static cast" and a "c-style cast". You will learn the differences between these in the Intermediate course. For now just know that, in the case of intbool conversions, both of the options are equivalent. However, the static_cast method is generally preferred for Modern C++.

Unintended Conversions

These conversions can cause issues where you least expect them to. One example is in the compound boolean expressions you learned about earlier. Normally, if you want to combine multiple boolean expressions together, you use the logical operators like so:

if (x > 10 && x < 25) { ... }

You may be tempted to rewrite the condition as 10 < x < 25. This will result in incorrect behavior, as this expression will always evaluate to true. This is because there is secretly an implicit bool🡢int conversion occurring. This expression gets interpreted as (10 < x) < 25. Let's see how this causes this condition to always evaluate to true by using the operator precedence table:

Incorrect operator chaining with x = 15
10 < x < 25    // Initial expression
10 < 15 < 25 // Substitute x
(10 < 15) < 25 // Operator precedence
(true) < 25 // Evaluate subexpression
1 < 25 // bool🡢int conversion
true // Evaluate subexpression
Incorrect operator chaining with x = 7
10 < x < 25   // Initial expression
10 < 7 < 25 // Substitute x
(10 < 7) < 25 // Operator precedence
(false) < 25 // Evaluate subexpression
0 < 25 // bool🡢int conversion
true // Evaluate subexpression

This same issue can occur in other similar scenarios, as well. For example, when checking if a single variable is one of many possibilities, the correct way would be x == 5 || x == 10 || x == 15. The tempting option of x == 5 || 10 || 15 will not work for a similar reason to the above. It will always be true. Let's see why:

Incorrect operator chaining with x = 5
x == 5 || 10 || 15     // Initial expression
5 == 5 || 10 || 15 // Substitute x
((5 == 5) || 10) || 15 // Operator precedence
((true) || 10) || 15 // Evaluate subexpression
(true || true) || 15 // int🡢bool conversion
true || 15 // Evaluate subexpression
true || true // int🡢bool conversion
true // Evaluate subexpression
Incorrect operator chaining with x = 7
x == 5 || 10 || 15     // Initial expression
7 == 5 || 10 || 15 // Substitute x
((7 == 5) || 10) || 15 // Operator precedence
((false) || 10) || 15 // Evaluate subexpression
(false || true) || 15 // int🡢bool conversion
true || 15 // Evaluate subexpression
true || true // int🡢bool conversion
true // Evaluate subexpression

Conclusion

In summary, we learned about:

This was a long journey, but the skills you have picked up here in this lesson are very fundamental to the road ahead. Read over the concepts presented in this lesson multiple times, as the basics of logic and conditions are a very important skill to have.

Booleans

The bool type

If you recall from the Variables lesson, one of basic types listed was bool. This type represents a boolean, which is a single true/false value.

The Boolean Expressions we learned about early in this Conditions lesson create a boolean value when evaluated. So, we can make variables that are the results of such boolean expressions, and then further use these bool variables in the conditions of if statements.

C++ provides two built-in bool constants - true and false. You can use these wherever a bool or boolean expression is expected. For example:

Boolean literals
bool var1 = true;
bool var2 = false;

There are more interesting things we can do with bool variables, too. Any boolean expression is valid to assign here. Combining this with if statements can make for shorter and more readable code in some cases.

Using boolean variables to determine the weather
std::string name;

std::cout << "Enter your first name: ";
std::cin >> name;

// User is lucky if their name has more than 5 characters
bool is_lucky = name.size() > 5;

// Try changing these values yourself and see what happens!
bool is_tuesday = true;
bool is_cloudy = false;

std::string weather = "sunny";

if (not is_tuesday and is_cloudy) {
weather = "raining";
} else if (is_tuesday) {
if (is_cloudy) {
weather = "overcast";
} else if (not is_lucky) {
weather = "downpouring";
}
}

std::cout << "It is currently " << weather << " in your location!";

The logical operators previously introduced can also be used to create new boolean variables.

Using logical operators on bools
bool is_precipitating = weather == "raining" or weather == "downpouring";
bool is_rainbow_made = is_precipitating and not is_cloudy;
bool is_boring_day = not is_rainbow_made;

Input/Output with bool

If you did any self-driven exploration with this new bool type, you may have noticed a peculiar thing... Printing out a bool does not display a true or false in the terminal. Instead, it prints out a 1 or a 0. This is simply a default behavior in C++ that is related to the next section.

You can easily change this behavior by changing one of std::cout's settings. Simply "print" out the std::boolalhpa built-in constant, and it will make all future boolean operations on std::cout print out true/false instead of 1/0.

Header include

Make sure you #include <iomanip> to use std::boolalpha.

Printing true/false
std::cout << true << " " << false << "\n";
std::cout << std::boolalpha;
std::cout << true << " " << false << "\n";
Output
1 0
true false

Conversely, std::cin by default will only accept a 0 or a 1 when inputting into a bool variable. This behavior can also be changed by "inputting" into the std::boolalpha flag. In the example below, the user will first input 0, which represents false. Then, they will input true once the std::boolalpha setting was applied.

Inputting true/false
bool var;

std::cout << "Integral form: ";
std::cin >> var;

std::cin >> std::boolalpha;

std::cout << "Alphanumeric form: ";
std::cin >> var;
Input/Output
Integral form: 1
Alphanumeric form: true

As an exercise, try modifying the weather example from above to accept user input, using the std::boolalpha modifier you just learned.

Fun Fact

The name "boolalpha" comes from a portmanteau of boolean and alphanumeric.

intbool conversions

C++ has another rather annoying behavior where booleans and integers can implicitly convert between each other. A boolean value of false is equivalent to an integer value of 0, and true is equivalent to 1. Conversely, an integral value of 0 is equivalent to a boolean value of false, and any non-zero integer is equivalent to true.

A sampling of int↔bool conversions
int x = true; // x is 1
int y = false; // y is 0

bool a = 1; // a is true
bool b = 25; // b is true
bool c = -194; // c is true
bool d = 0; // d is false

While this behavior may seem neat, it can unexpectedly crop up in many places where they are not wanted. For this reason, if you want to intentionally trigger an intbool conversion, then you should cast the value.

Performing a cast
int x = static_cast<int>(true); // Modern-style cast
int y = (int) false; // C-style cast

bool a = static_cast<bool>(1);
bool b = (bool) 0;

There are two primary ways to perform a cast like this in C++ - a "static cast" and a "c-style cast". You will learn the differences between these in the Intermediate course. For now just know that, in the case of intbool conversions, both of the options are equivalent. However, the static_cast method is generally preferred for Modern C++.

Unintended Conversions

These conversions can cause issues where you least expect them to. One example is in the compound boolean expressions you learned about earlier. Normally, if you want to combine multiple boolean expressions together, you use the logical operators like so:

if (x > 10 && x < 25) { ... }

You may be tempted to rewrite the condition as 10 < x < 25. This will result in incorrect behavior, as this expression will always evaluate to true. This is because there is secretly an implicit bool🡢int conversion occurring. This expression gets interpreted as (10 < x) < 25. Let's see how this causes this condition to always evaluate to true by using the operator precedence table:

Incorrect operator chaining with x = 15
10 < x < 25    // Initial expression
10 < 15 < 25 // Substitute x
(10 < 15) < 25 // Operator precedence
(true) < 25 // Evaluate subexpression
1 < 25 // bool🡢int conversion
true // Evaluate subexpression
Incorrect operator chaining with x = 7
10 < x < 25   // Initial expression
10 < 7 < 25 // Substitute x
(10 < 7) < 25 // Operator precedence
(false) < 25 // Evaluate subexpression
0 < 25 // bool🡢int conversion
true // Evaluate subexpression

This same issue can occur in other similar scenarios, as well. For example, when checking if a single variable is one of many possibilities, the correct way would be x == 5 || x == 10 || x == 15. The tempting option of x == 5 || 10 || 15 will not work for a similar reason to the above. It will always be true. Let's see why:

Incorrect operator chaining with x = 5
x == 5 || 10 || 15     // Initial expression
5 == 5 || 10 || 15 // Substitute x
((5 == 5) || 10) || 15 // Operator precedence
((true) || 10) || 15 // Evaluate subexpression
(true || true) || 15 // int🡢bool conversion
true || 15 // Evaluate subexpression
true || true // int🡢bool conversion
true // Evaluate subexpression
Incorrect operator chaining with x = 7
x == 5 || 10 || 15     // Initial expression
7 == 5 || 10 || 15 // Substitute x
((7 == 5) || 10) || 15 // Operator precedence
((false) || 10) || 15 // Evaluate subexpression
(false || true) || 15 // int🡢bool conversion
true || 15 // Evaluate subexpression
true || true // int🡢bool conversion
true // Evaluate subexpression

Conclusion

In summary, we learned about:

This was a long journey, but the skills you have picked up here in this lesson are very fundamental to the road ahead. Read over the concepts presented in this lesson multiple times, as the basics of logic and conditions are a very important skill to have.