12

I'm new to c++ and am curious how the compiler handles lazy evaluation of booleans. For example,

if(A == 1 || B == 2){...}

If A does equal 1, is the B==2 part ever evaluated?

tinkertime
  • 2,972
  • 4
  • 30
  • 45
  • 1
    wow, that was the quickest 6 responses ever. thanks guys. – tinkertime Nov 25 '09 at 18:43
  • 3
    You could have tested that by creating a function with a side effect (i.e., print something to standard out) and placing it in the second position (assuming that the first condition is false). Also, the documentation tells us that || is a short circuiting operator. – Ed S. Nov 25 '09 at 18:45
  • 1
    but then where would be the fun in watching all of these answers flow in? – tinkertime Nov 25 '09 at 18:50
  • note that it doesn't have anything to do with lazy evaluation. While it's true that lazy evaluating languages make this behavior trivial to implement; in C/C++ case, it's just compiled into the equivalent of a series of nested ifs. – Javier Nov 25 '09 at 19:02
  • 6
    @Ed: Tests are not a substitute for standards and documentation. – David Thornley Nov 25 '09 at 19:10

8 Answers8

23

No, the B==2 part is not evaluated. This is called short-circuit evaluation.

Edit: As Robert C. Cartaino rightly points out, if the logical operator is overloaded, short-circuit evaluation does not take place (that having been said, why someone would overload a logical operator is beyond me).

Community
  • 1
  • 1
James McNellis
  • 348,265
  • 75
  • 913
  • 977
  • My experience is that some compilers will evaluate B==2 when strong optimizations are enabled. Although I've now switched to GCC, I recall MSVC 6 or so would evaluate B==2 prior to A==1 in release mode. – fuzzyTew Mar 21 '16 at 01:00
  • 3
    @fuzzyTew you either wrong or that compiler is buggy, it must not evaluate right side if left is true. – Slava Dec 08 '17 at 17:13
  • @Slava that is not entirely true. The compiler can spot that neither operation has (relevant) side-effects and evaluate them in whatever order it deems optimal as per the as-if rule. – patatahooligan Sep 13 '19 at 16:13
21

Unless the || operator is overloaded, the second expression will not be evaluated. This is called "short-circuit evaluation."

In the case of logical AND (&&) and logical OR (||), the second expression will not be evaluated if the first expression is sufficient to determine the value of the entire expression.

In the case you described above:

if(A == 1 || B == 2) {...}

...the second expression will not be evaluated because

TRUE || ANYTHING, always evaluates to TRUE.

Likewise,

FALSE && ANYTHING, always evaluates to FALSE, so that condition will also cause a short-circuit evaluation.

A couple of quick notes

  • Short circuit evaluation will not apply to overloaded && and || operators.
  • In C++, you are guaranteed that the first expression will be evaluated first. Some languages do not guarantee the order of evaluation and VB doesn't do short-circuit evaluation at all. That's important to know if you are porting code.
Community
  • 1
  • 1
Robert Cartaino
  • 27,494
  • 6
  • 45
  • 67
  • 2
    "VB doesn't do short-circuit evaluation at all"--that's only true with the `And` and `Or` operators. But the [`AndAlso`](https://msdn.microsoft.com/en-us/library/cb8x3kfz.aspx) and [`OrElse`](https://msdn.microsoft.com/en-us/library/ea1sssb2.aspx) operators specifically _do_ perform short-circuit evaluation. – villapx Sep 22 '16 at 14:00
1

The B==2 part is not evaluated.

Be careful! Don't put something like ++B==2 over there!

eleven81
  • 6,301
  • 11
  • 37
  • 48
1

C++ applies short circuiting to Boolean expression evaluation so, the B == 2 is never evaluated and the compiler may even omit it entirely.

D.Shawley
  • 58,213
  • 10
  • 98
  • 113
  • Oh come on, this answer was missing so much context it might as well have been an answer saying "potato". Maybe you made a bad assumption because A was capitalized, but it was never specified to be a macro or even a static const. If it's a variable, the compiler would never assume that the clause would be true to the extent that it would omit the B==2 check from being possible within the code. And if you think that should be fundamentally obvious to anyone reading, you've never taught someone their first programming language. – codetaku Apr 04 '17 at 14:55
  • @codetaku ... context aside, you cannot assume that the `B == 2` branch is *ever* evaluated and if `A` is provably a constant expression that is equal to `1` a good compiler will completely omit the branch when instructed to optimize for code size. The code will be compiled but the optimizer is free to strip dead branches if they will never be executed. As for early programmers, it is important to understand basic concepts like what a linker or optimizing compiler does to your code lest you make bad assumptions. – D.Shawley Apr 05 '17 at 12:05
1

The compiler handles this by generating intermediate jumps. For the following code:

if(A == 1 || B == 2){...}

compiled to pseudo-assembler, might be:

    load variable A
    compare to constant 1
    if equal, jump to L1
    load variable B
    compare to constant 2
    if not equal, jump to L2
L1:
    ... (complete body of if statement)
L2:
    (code after if block goes here)
Greg Hewgill
  • 951,095
  • 183
  • 1,149
  • 1,285
  • you don't know that. You compiler might decide that A is always 1 for instance and completely discard that check. – shoosh Nov 25 '09 at 18:52
  • 4
    That's true, but that's an optimisation and not relevant for this example. – Greg Hewgill Nov 25 '09 at 19:03
  • 1
    in addition to @shoosh's point, the compiler may also decide that the addition of another point of possible branch misprediction isn't cheaper than just combining the comparisons, and because B has no side-effects the instructions it emits always do both comparisons and only have one branch point. – Caleth Jun 24 '16 at 10:41
1

This is short-circuit evaluation, as James says. Lazy evaluation is something entirely different.

Conrad Meyer
  • 2,851
  • 21
  • 24
0

No it's not.

Same with &&, if one is wrong, it doesn't bother evaluating the other one.

danpker
  • 593
  • 1
  • 5
  • 15
0

B == 2 is never evaluated.

See Short-Circuit Evaluation for more information.

Nick Presta
  • 28,134
  • 6
  • 57
  • 76