Comparison and Logical Operators
Programs are useful because they can make decisions based on data. To make such decisions, we often need to compare values and build expressions on which those decisions rest. Comparison and logical operators let you do just that.
Unlike the arithmetic operators we saw before, these operators don’t produce numbers. They produce a truth value: something is either true or false.
Comparison results have a type
We have already seen how C++ has a type called bool that holds exactly two values: true or false. In C++, an expression like 3 < 5 evaluates to true, since 3 is less than 5. And that result has a type: bool.
In practice, you use comparisons directly in decision making. For now, storing the result in a variable is the clearest way to see what’s happening:
On line 5, >= represents the greater than or equal to operator, which is why the expression evaluates to true. Recall that cout prints 1 for true and 0 for false.
Try changing age to 17 to see how the output becomes 0. Because the expression (age >= 18) is no longer satisfied and evaluates to false.
Comparison operators
These six operators compare two values and return true or false:
| Operator | Meaning |
|---|---|
== | equal to |
!= | not equal to |
< | less than |
> | greater than |
<= | less than or equal to |
>= | greater than or equal to |
You can compare different values with these operators:
You can compare double, char, and bool values the same way:
Logical operators
A simple comparison is not always enough. Sometimes, you need to check whether two things are both true, or whether at least one is true. That’s what logical operators do.
The && operator (and)
An expression using && evaluates to true only when the expressions on both sides are true.
If you set has_ticket = false on line 5, can_enter will become false despite the age check still holding true.
Now that we understand the basic mechanism, take a moment to think about the expression:
18 <= age <= 30Do you expect the expression to evaluate to false if age is set to 40?
But it doesn’t. The expression evaluates left to right, so (18 <= age) <= 30 becomes 1 <= 30, which is always true. For this reason, expressions like these are written with &&:
(age >= 18) && (age <= 30)The || operator (or)
An expression using || evaluates to true if at least one side is true.
|| is only false when both sides are false.
The ! operator (not)
! flips a boolean. !true is false, and !false is true.
This reads almost like English: “not logged in.” Use ! when the negative phrasing is the clearer one.
Short-circuit evaluation
Under the hood, C++ doesn’t always evaluate both sides of && or ||:
- With
&&: if the left side isfalse, the whole expression always evaluates tofalse. So C++ doesn’t bother evaluating the right side. - With
||: if the left side istrue, the whole expression will always evaluate totrue, so C++ skips evaluating the right side.
The idea of short-circuiting comes in handy, for example, as shown in the following code.
Suppose count arrived as zero from user input. On line 7, count != 0 evaluates to false. Checking it first means division is never reached due to short-circuiting. In this way, a divide-by-zero runtime error is avoided.
Try removing count != 0 and running it to see how the program crashes.
Operator precedence with logical operators
! has the highest precedence and applies to whatever comes immediately after it. So in !a && b, ! applies only to a, not to (a && b).
Next, && takes precedence over ||. So a || b && c means a || (b && c).
Rather than memorizing the exact precedence table, use parentheses whenever you mix && and || in the same expression:
// Ambiguous to a reader:bool result = is_admin || is_moderator && is_verified;// Clear:bool result = is_admin || (is_moderator && is_verified);Parentheses cost nothing and make your intent explicit.
Checkpoint
What does this expression evaluate to when day is 30 and month is 4?
(day >= 1) &&
(
(month == 2 && day <= 29) ||
(day <= 30 && (month == 4 || month == 6 || month == 9 || month == 11)) ||
day <= 31
)What does this expression evaluate to when balance is 50 and account_status is "frozen"?
!(balance < 0) && (account_status != "frozen")