While relational (comparison) operators can be used to test whether a particular condition is true or false, they can only test one condition at a time. Often we need to know whether multiple conditions are true simultaneously. For example, to check whether we’ve won the lottery, we have to compare whether all of the multiple numbers we picked match the winning numbers. In a lottery with 6 numbers, this would involve 6 comparisons, *all* of which have to be true. In other cases, we need to know whether any one of multiple conditions is true. For example, we may decide to skip work today if we’re sick, or if we’re too tired, or if won the lottery in our previous example. This would involve checking whether *any* of 3 comparisons is true.

Logical operators provide us with the capability to test multiple conditions.

C++ has 3 logical operators:

Operator | Symbol | Form | Operation |
---|---|---|---|

Logical NOT | ! | !x | true if x is false, or false if x is true |

Logical AND | && | x && y | true if both x and y are true, false otherwise |

Logical OR | || | x || y | true if either x or y are true, false otherwise |

**Logical NOT**

You have already run across the logical NOT unary operator in lesson 4.9 -- Boolean values. We can summarize the effects of logical NOT like so:

Logical NOT (operator !) | |
---|---|

Operand | Result |

true | false |

false | true |

If *logical NOT’s* operand evaluates to true, *logical NOT* evaluates to false. If *logical NOT’s* operand evaluates to false, *logical NOT* evaluates to true. In other words, *logical NOT* flips a Boolean value from true to false, and vice-versa.

Logical NOT is often used in conditionals:

1 2 3 4 5 |
bool tooLarge { x > 100 }; // tooLarge is true if x > 100 if (!tooLarge) // do something with x else // print an error |

One thing to be wary of is that *logical NOT* has a very high level of precedence. New programmers often make the following mistake:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
#include <iostream> int main() { int x { 5 }; int y { 7 }; if (! x > y) std::cout << "x is not greater than y\n"; else std::cout << "x is equal to or greater than y\n"; return 0; } |

This program prints:

x is equal to or greater than y

But *x* is not equal to or greater than *y*, so how is this possible? The answer is that because the *logical NOT* operator has higher precedence than the greater than operator, the expression `! x > y`

actually evaluates as `(!x) > y`

. Since *x* is 5, !x evaluates to *0*, and `0 > y`

is false, so the *else* statement executes!

The correct way to write the above snippet is:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
#include <iostream> int main() { int x { 5 }; int y { 7 }; if (!(x > y)) std::cout << "x is not greater than y\n"; else std::cout << "x is equal to or greater than y\n"; return 0; } |

This way, `x > y`

will be evaluated first, and then logical NOT will flip the Boolean result.

Best practice

If *logical NOT* is intended to operate on the result of other operators, the other operators and their operands need to be enclosed in parenthesis.

Simple uses of *logical NOT*, such as `if (!value)`

do not need parenthesis because precedence does not come into play.

Logical OR

The *logical OR* operator is used to test whether either of two conditions is true. If the left operand evaluates to true, or the right operand evaluates to true, or both are true, then the *logical OR* operator returns true. Otherwise it will return false.

Logical OR (operator ||) | ||
---|---|---|

Left operand | Right operand | Result |

false | false | false |

false | true | true |

true | false | true |

true | true | true |

For example, consider the following program:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
#include <iostream> int main() { std::cout << "Enter a number: "; int value {}; std::cin >> value; if (value == 0 || value == 1) std::cout << "You picked 0 or 1\n"; else std::cout << "You did not pick 0 or 1\n"; return 0; } |

In this case, we use the logical OR operator to test whether either the left condition (value == 0) or the right condition (value == 1) is true. If either (or both) are true, the *logical OR* operator evaluates to true, which means the *if statement* executes. If neither are true, the *logical OR* operator evaluates to false, which means the *else statement* executes.

You can string together many *logical OR* statements:

1 2 |
if (value == 0 || value == 1 || value == 2 || value == 3) std::cout << "You picked 0, 1, 2, or 3\n"; |

New programmers sometimes confuse the *logical OR* operator (||) with the *bitwise OR* operator (|). Even though they both have *OR* in the name, they perform different functions. Mixing them up will probably lead to incorrect results.

Logical AND

The *logical AND* operator is used to test whether both operands are true. If both operands are true, *logical AND* returns true. Otherwise, it returns false.

Logical AND (operator &&) | ||
---|---|---|

Left operand | Right operand | Result |

false | false | false |

false | true | false |

true | false | false |

true | true | true |

For example, we might want to know if the value of variable *x* is between *10* and *20*. This is actually two conditions: we need to know if *x* is greater than *10*, and also whether *x* is less than *20*.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
#include <iostream> int main() { std::cout << "Enter a number: "; int value {}; std::cin >> value; if (value > 10 && value < 20) std::cout << "Your value is between 10 and 20\n"; else std::cout << "Your value is not between 10 and 20\n"; return 0; } |

In this case, we use the *logical AND* operator to test whether the left condition (value > 10) AND the right condition (value < 20) are both true. If both are true, the *logical AND* operator evaluates to true, and the *if statement* executes. If neither are true, or only one is true, the *logical AND* operator evaluates to false, and the *else statement* executes.

As with *logical OR*, you can string together many *logical AND* statements:

1 2 3 4 |
if (value > 10 && value < 20 && value != 16) // do something else // do something else |

If all of these conditions are true, the *if statement* will execute. If any of these conditions are false, the *else statement* will execute.

Short circuit evaluation

In order for *logical AND* to return true, both operands must evaluate to true. If the first operand evaluates to false, *logical AND* knows it must return false regardless of whether the second operand evaluates to true or false. In this case, the *logical AND* operator will go ahead and return false immediately without even evaluating the second operand! This is known as short circuit evaluation, and it is done primarily for optimization purposes.

Similarly, if the first operand for *logical OR* is true, then the entire OR condition has to evaluate to true, and the second operand won’t be be evaluated.

Short circuit evaluation presents another opportunity to show why operators that cause side effects should not be used in compound expressions. Consider the following snippet:

1 2 |
if (x == 1 && ++y == 2) // do something |

if *x* does not equal *1*, the whole condition must be false, so ++y never gets evaluated! Thus, *y* will only be incremented if *x* evaluates to 1, which is probably not what the programmer intended!

Warning

Short circuit evaluation may cause *Logical OR* and *Logical AND* to not evaluate one operand. Avoid using expressions with side effects in conjunction with these operators.

As with logical and bitwise OR, new programmers sometimes confuse the *logical AND* operator (&&) with the *bitwise AND* operator (&).

Mixing ANDs and ORs

Mixing *logical AND* and *logical OR* operators in the same expression often can not be avoided, but it is an area full of potential dangers.

Many programmers assume that *logical AND* and *logical OR* have the same precedence (or forget that they don’t), just like addition/subtraction and multiplication/division do. However, *logical AND* has higher precedence than *logical OR*, thus *logical AND* operators will be evaluated ahead of *logical OR* operators (unless they have been parenthesized).

New programmers will often write expressions such as `value1 || value2 && value3`

. Because *logical AND* has higher precedence, this evaluates as `value1 || (value2 && value3)`

, not `(value1 || value2) && value3`

. Hopefully that’s what the programmer wanted! If the programmer was assuming left to right evaluation (as happens with addition/subtraction, or multiplication/division), the programmer will get a result he or she was not expecting!

When mixing *logical AND* and *logical OR* in the same expression, it is a good idea to explicitly parenthesize each operator and its operands. This helps prevent precedence mistakes, makes your code easier to read, and clearly defines how you intended the expression to evaluate. For example, rather than writing `value1 && value2 || value3 && value4`

, it is better to write `(value1 && value2) || (value3 && value4)`

.

Best practice

When mixing *logical AND* and *logical OR* in a single expression, explicitly parenthesize each operation to ensure they evaluate how you intend.

De Morgan’s law

Many programmers also make the mistake of thinking that `!(x && y)`

is the same thing as `!x && !y`

. Unfortunately, you can not “distribute” the *logical NOT* in that manner.

De Morgan’s law tells us how the *logical NOT* should be distributed in these cases:

`!(x && y)`

is equivalent to `!x || !y`

`!(x || y)`

is equivalent to `!x && !y`

In other words, when you distribute the *logical NOT*, you also need to flip *logical AND* to *logical OR*, and vice-versa!

This can sometimes be useful when trying to make complex expressions easier to read.

Where’s the logical exclusive or (XOR) operator?

*Logical XOR* is a logical operator provided in some languages that is used to test whether an odd number of conditions is true.

Logical XOR | ||
---|---|---|

Left operand | Right operand | Result |

false | false | false |

false | true | true |

true | false | true |

true | true | false |

C++ doesn’t provide a *logical XOR* operator. Unlike *logical OR* or *logical AND*, *logical XOR* cannot be short circuit evaluated. Because of this, making an *logical XOR* operator out of *logical OR* and *logical AND* operators is challenging. However, you can easily mimic *logical XOR* using the *inequality* operator (!=):

1 |
if (a != b) ... // a XOR b, assuming a and b are Booleans |

This can be extended to multiple operands as follows:

1 |
if (a != b != c != d) ... // a XOR b XOR c XOR d, assuming a, b, c, and d are Booleans |

Note that the above XOR patterns only work if the operands are Booleans (not integers). If you need a form of *logical XOR* that works with non-Boolean operands, you can static_cast them to bool:

1 |
if (static_cast<bool>(a) != static_cast<bool>(b) != static_cast<bool>(c) != static_cast<bool>(d)) ... // a XOR b XOR c XOR d, for any type that can be converted to bool |

Quiz time

Question #1

Evaluate the following expressions.

Note: in the following answers, we “explain our work” by showing you the steps taken to get to the final answer. The steps are separated by a *=>* symbol. For example “(true || false) => true” means we evaluated “(true || false)” to arrive at the value “true”.

a) (true && true) || false

b) (false && true) || true

c) (false && true) || false || true

d) (5 > 6 || 4 > 3) && (7 > 8)

e) !(7 > 6 || 3 > 4)

5.x -- Chapter 5 summary and quiz |

Index |

5.6 -- Relational operators and floating point comparisons |

"Don't assume the compiler will evaluate in the order you think it will" seems to be a high takeaway in these sections!

I.e., be explicit and use parentheses!

Hi Alex!

In the snippet just after "Logical NOT is often used in conditionals:" why is the expression in parenthesis? I thought it could be without them?

Also, I think the correct way to fix the precedence issue example is to use != instead of ! and ==, not to use parenthesis. If you want to keep the parenthesis example, I think one of the operators with < or > in them would be less contrived.

I removed the offending parenthesis.

I also updated the example per your feedback. Thanks for the suggestion!

result of quiz 5 is not true??

No. The expression inside the parenthesis evaluate to true, but then that is negated because of the ! in front, so it becomes a false.

On logical OR you should also say that if left operand is true that it WONT evaluate the right operand

Thanks for the feedback. I've updated the language to make it clear that the evaluation of the right operand doesn't happen.

In the last example, why is casting to bool needed? Wouldn't casting integers to bool be redundant since any non-zero integers evaluates to true and false otherwise already?

Assume

a = 1

b = 2

c = 3

d = 4

Without cast

With cast

I see, but why would we ever want to cast int to bool? I feel like it doesn't make sense at all.

Because there are a lot of programmers who use integers to denote boolean variables, by making integer 0 be boolean false and any non-zero integer be boolean true. This is a remnant from older C programming, because unlike C++, C doesn't have a built-in boolean datatype by default, so all boolean logic was executed with ints.

Greeting,

I want to know learn where Non-logical operators can be used ?

I mean these operators ' & , | ' .

Lesson O.3.8

Thank you so much

In the first code snippit of Logical OR, on line 9, it is written as:

Whereas, in other examples of code it would be written as:

Just a small little inconsistency I noticed.

Thanks, formatting fixed!

Just above the "Where’s the logical exclusive or (XOR) operator?" heading:

"This can sometimes be useful when trying to make up complex expressions easier to read."

Shouldn't it be "... trying to make complex expressions ..." ?

"Simple uses of logical NOT, such as if (!bValue) do not need parenthesis because precedence does not come into play."

I would like to add the situation where bValue is a preprocessor macro. bValue could be replaced by "5 == 7", which would break the thing.

You shouldn't be using preprocessor macros with substitution text. :)

Hi Alex!

Since you appreciate inconsistencies being flagged up, the second and third code snippets in this lesson feature 'cout' as opposed to 'std::cout'.

Hope that helps!

Thanks! Fixed.

Hi this was a really great tutorial. So simplified. Though 1 question. Would you recommend to use logical operators in conditional operators?.. Although the idea sounds kinda complicated to me. Or should I practice?

Using logical operators in conditionals is very common, so better to practice than avoid. :)

Hi,

Is there a way of telling the compiler 1 through 25 or you have to use logical AND every time?

Hi Gabe!

What do you mean by "1 through 25"? Can you give an example of what you have in mind?

I make a variable that gets assigned by an rng, then make an if statement that prints a string based on the value the rng comes up with. So, what I mean is can I write "if rngoutcome = 1 through 25

std::cout << string;"

Do you mean this?

References

Lesson 3.1 - Operator precedence and associativity

oh yea makes sense

thanks

This is just a minor observation. The code snippet immediately under Logical AND writes (on line 7)

instead of

as has been done in other examples.

Thanks. Fixed!

C++ provides a logical xor operator in the form of '^', for example:

Which is the truth table for XOR.

Hi Farshid!

^ is the binary xor operator and therefore covered in lesson 3.8 (Bitwise operators).

!= is used as a logical xor

Alright, thanks for clarification. I am yet to arrive at 3.8 :D

The short circuit evaluation would also apply to the AND operator - if the first operand is false, the result is false without having to evaluate the second operand. I would be concerned that the optimiser might also evaluate just the second operand (particularly if it is already a boolean variable) and skip evaluating the first operand if the second operand is true (for OR) or false (for AND), so does C++ guarantee the order of evaluation?

Thanks

Hi Trevor!

Conditions will be executed left to right unless the && or || operator have been overloaded to behave differently (Chapter 9).

I've never come across a class doing this, so I'd say you're safe to assume the default execution order.

(Initial incorrect response removed to confusion -- see the next response for correct answer)

ISO N4659 §8.14

"Unlike &, && guarantees left-to-right

evaluation: the second operand is not evaluated if the first operand is false."

(§8.15 is analogical for the logical or)

Correct me if I'm wrong, I think this means (a && b) will execute a first guaranteed.

I stand corrected.

It appears that && (and ||) do guarantee left to right order of evaluation, but only for non-overloaded functions. If you overload && or ||, no short circuit evaluation or guaranteed ordering will take place.

can we solve fifth question as:

!(7 > 6 || 3 > 4) => !(true || false) => (false && true) => false

?

Logically yes. But I'd argue it's less correct because when evaluating an expression, things inside the parenthesis should take precedence.

Isn't the above code the same as the code below?

yes,

produces the same result as

but be careful:

in first example you use "logical not" operator that has level 3 right to left (R->L) precedence,

but in second example you use "inequality" operator that has level 9 left to right (L->R) precedence.

They produce the same result but they are not the same thing.

Ok that's good to know, thanks for the reply. :)

Yes.

HI Alex, Great tutorials you are such a Great teacher. are these expressions equivalent?

if not which is better?

Yes, they're equivalent, but C++ doesn't understand the latter, so we have to use the former.

Hi Alex,

De Morgan’s law

Many programmers also make the mistake of thinking that !(x && y) is the same thing as !x && !y. Unfortunately, you can not “distribute” the logical NOT in that manner.

De Morgan’s law tells us how the logical NOT should be distributed in these cases:

!(x && y) is equivalent to !x || !y

!(x || y) is equivalent to !x && !y

In other words, when you distribute the logical NOT, you also need to flip logical AND to logical OR, and vice-versa!

I was trying to better understand de morgans law then i came up with this solution to try to understand how it works is it correct ?

!(x and y) is equivalent to (!x and !y or !y and !x or !y and !y or !x and !x)

!(x or y) is equivalent to (!x or !y and !y or !x and !y or !y and !x or !x)

Hi Alex,

There is one thing I don't get. You wrote

I assume that the XOR of more booleans is true whenever (and only when) exactly one of the booleans are true. Am I right?

But this dos not seem true to me, even with only three booleans. In fact if

then

But, perhaps, I just got wrong what is the XOR of multi booleans. So,

would just mean

which means: if c is true then a and b are either both false or either both true, if c is false then one of a and b is true and the other is false (in order for the statement to be true), which in turn means that exactly one of the three is false or they are all true. I don't know in which situations this expression might be useful. Especially with more than three variables the logical table becomes quite complex and hard to understand.

Thanks.

XOR of multiple booleans evaluates to true whenever an odd number of the inputs are true, and false whenever an even number of inputs are true. XOR is rarely used.

Cool! Thank you.

Hi,I am a beginner of C++.How do I start..? What Basics should a beginner must know before his coding..?

Start at the beginning of the tutorial. It will tell you everything you need to know.

Is

evaluated to

or to

? thanks.

Operator != evaluates from left to right, so (a != b != c != d) evaluates as (((a != b) != c) != d).

Typo... you put "then" instead of "than" in the statement "and also whether x is less then 20"

And sorry about my English but I'm Argentinian so I speak Spanish.

Have a nice day and your tutorial is amazing!!!

Thanks, I've fixed the typo. Appreciate you pointing it out.

i want to write a program where i just want to pick out cars which are black and has a brand name of toyota... now i am facing the problem that where will i declare the flag of black and toyota..

although i know this can be also done with out flag... just want to know

[/code]

#include <iostream>

int main()

{

std::cout<< "enter colour";

int colour;

std::cin>>colour;

std::cout<< "enter brand";

int brand;

std::cin>>brand;

if(colour==1 && brand==0)

{

black= 1; //colour flag

brand toyota=0; //brand flag

std::cout<<"pick yhe car"<< std::endl;

}

else

{

std::cout<<"pick another"<<std::endl;

}

return 0;

}

Alex and others please help

This evaluates as

which isn't what you want. You need to "distribute the variable", like so:

(Note: I changed your logical ORs to logical ANDs as well)

Thanks again Alex

Might be a good idea to say how you actually type a logical or operator (Press alt gr + that three character key underneath esc)

How you type | depends on the layout of your keyboard. In the US it's shift-\.