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?
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).
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.
The B==2 part is not evaluated.
Be careful! Don't put something like ++B==2 over there!
C++ applies short circuiting to Boolean expression evaluation so, the B == 2 is never evaluated and the compiler may even omit it entirely.
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)
This is short-circuit evaluation, as James says. Lazy evaluation is something entirely different.
No it's not.
Same with &&, if one is wrong, it doesn't bother evaluating the other one.
B == 2 is never evaluated.
See Short-Circuit Evaluation for more information.
Related
This question already has answers here:
Is short-circuiting logical operators mandated? And evaluation order?
(7 answers)
Closed 6 years ago.
I was trying to find the order of evaluation inside if clause when more than 2 conditions are specified. I found multiple results to talk about how 2 conditions are evaluated. My questions is when I have something like,
it=seqMap.find(a);
if( a !="" && it==seqMap.end() || isEven )
{
//Do something
}
I understand that this is not the right way to write code and braces are important but I am trying to understand how this will work, out of curiosity.
The built-in boolean operators impose a strict sequencing. They have shortcut evaluation where the second argument is not even evaluated if the first one determines the outcome. This is important in cases where evaluation of the second argument could have Undefined Behavior.
User defined boolean operators do not, as a rule, provide shortcut evaluation.
It's possible to emulate the effect but C++ doesn't really support this. C# does.
A && B || C
… is parsed as
(A && B) || C
… because && effectively has higher precedence than ||.
However, the C++ grammar is not defined in terms of precedence. Rather it's designed to emulate a precedence, which then appears as an emergent feature of the grammar. And this means that a naïve precedence view in some cases can indicate an incorrect parse, so use precedence reasoning with care.
It will first evaluate
a !="" && it==seqMap.end()
If a !="" evaluates to false then it will check
a !=""|| isEven
Otherwise if a !="" evaluates to true then, it==seqMap.end() will be evaluated and
finally the the answer of a !="" && it==seqMap.end() will be OR'ed with isEven
In C++ the logical AND operator has higher precedene than the logical OR operator.
Also the logical AND and OR operators have shortcut evaluation. If the first condition of AND is false, then the second condition will not be evaluated. Similarly, if the first condition of OR is true, then the second condition will not be evaluated.
For further reference on operator precedene:
http://en.cppreference.com/w/cpp/language/operator_precedence
This question already has answers here:
Is short-circuiting logical operators mandated? And evaluation order?
(7 answers)
Closed 5 years ago.
When encountering a (bool1 && bool2), does c++ ever attempts to check bool2 if bool1 was found false or does it ignore it the way PHP does?
Sorry if it is too basic of a question, but I really could not find a mentioning of that neither in Schildt nor on the Internet.
Yes, the && operator in C++ uses short-circuit evaluation so that if bool1 evaluates to false it doesn't bother evaluating bool2.
"Short-circuit evaluation" is the fancy term that you want to Google and look for in indexes.
The same happens with the || operator, if bool1 evaluates to true then the whole expression will evaluate to true, without evaluating bool2.
In case you want to evaluate all expressions anyway you can use the & and | operators.
C++ does use short-circuit logic, so if bool1 is false, it won't need to check bool2.
This is useful if bool2 is actually a function that returns bool, or to use a pointer:
if ( pointer && pointer->someMethod() )
without short-circuit logic, it would crash on dereferencing a NULL pointer, but with short-circuit logic, it works fine.
That is correct (short-cicuit behavior). But beware: short-circuiting stops if the operator invoked is not the built-in operator, but a user-defined operator&& (same with operator||).
Reference in this SO
The && operator short circuits in C++ - if bool1 was false in your example, bool2 wouldn't be checked/executed.
This is called short-circuit evaluation (Wikipedia)
The && operator is a short circuit operator in C++ and it will not evaluate bool2 if bool1 is false.
Short-circuit evaluation denotes the semantics of some Boolean operators in some programming languages in which the second argument is only executed or evaluated if the first argument does not suffice to determine the value of the expression: for instance, when the first argument of the AND function evaluates to false, the overall value must be false; and when the first argument of the OR function evaluates to true, the overall value must be true.
In C++, both && and || operators use short-circuit evaluation.
What you're referring to is short circuit evaluation. I thought that it may be compiler specific, however that article I linked to shows it as language specific, and C++ does adhere. If it is indeed compiler specific, I can't imagine a compiler that wouldn't follow it. The day to day compiler I use at the moment, VS 2008, does. Basically it will follow the operator precedence, and as soon as the condition result is guaranteed,
What is the computation order of the equal priority operands in C / C++ ?
For example in following piece of code:
if ( scanf("%c", &ch_variable) && (ch_variable == '\n') )
Can I be sure that 1st expression inside the IF statement is performed before the 2nd (i.e. the value of ch_variable compared, is a newly scanned one)?
Or is it somehow decided by compiler? And if so, how this decision is being made?
BTW, I usually use the following flags for compilation:
-std=c99 -O0 -pedantic -Wall -ansi
Can I be sure that 1st expression inside the IF statement is performed before the 2nd (i.e. the value of ch_variable compared, is a newly scanned one)?
Yes - the first expression (the scanf call) is evaluated first, and what's more the second doesn't happen at all if the scanf call returns 0 - see below. That's short circuit evaluation.
Broader discussion.
Read about the operator precedence at cppreference.com
Summarily - operators are arranged in groups with well-defined relative precedence (e.g. '*' has higher precendence than +, as per usage in mathematics), and left-to-right or right-to-left associativity (e.g. a + b + c is left associative and evaluated as (a + b) + c, but a = b = c is right-associative and evaluated as a = (b = c)).
In your code:
if (scanf("%c", &ch_variable) && (ch_variable == '\n') )
The ( and ) work as you'd expect - overriding any implicit precedence between && and == (but in this case the precedence is the same). && is therefore uncontested, and as a short-circuit operator it ensures its left argument is converted - if necessary - to boolean (so if scanf returns 0 it's deemed false, otherwise true), then if and only if that's true does it evaluate the right-hand-side argument, and only if they're both true does the if statement run the following statement or {} statement block.
This has nothing to do with "priority" (operator precedence), but with the order of evaluation of sub-expressions.
The && operator is a special case in C, as it guarantees order of evaluation from left to right. There is a sequence point between the evaluation of the left operand and the right operand, meaning that the left operation will always be executed/evaluated first.
Many C operators do not come with this nice guarantee, however. Imagine the code had been like this:
if ( (scanf("%c", &ch_variable)!=0) & (ch_variable == '\n') )
This is obfuscated code but it logically does the same thing as your original code. With one exception: the & operator behaves as most operators in C, meaning there are no guarantees that the left operand will get evaluated before the right one. So my example has the potential of evaluating ch_variable before it has been given a valid value, which is a severe bug.
The order of evaluation of such sub-expressions is unspecified behavior, meaning that the compiler is free to evaluate any side first. It doesn't need to document what it will do and it doesn't even need to pick the same side consistently between compilations, or even pick the same side consistently throughout the program.
The language was deliberately designed this way to allow compilers to optimize the code in the best possible way, from case to case.
Yes, absolutely, anything involving && and || (except if you use operator&& or operator|| - which is one of the main reasons NOT to use these operators) is "strict short cutting" - in other words, if the overall outcome of the result can be determined, the rest is not evaluated, and the order is strictly left to right - always, by the language standard. [Of course, if the compiler can be SURE it's completely safe, it may reorder things, but that is part of the "as-if" definition of the standard - if the compiler behaves "as-if" it is doing it the way the standard says].
Beware that:
if(scanf("%c", &ch_variable) && scanf("%c", &second_variable))
{
...
}
else
{
...
}
may not have set "second_variable" at all in the else part, so it's unsafe to use it at this point.
I would aos use scanf("%c", &ch_variable) > 0 instead - as it could return -1 at EOF, which is true in your case, without an intermediate 0 return value...
It's guaranteed that the first expression is evaluated before the second one.
See Is short-circuiting logical operators mandated? And evaluation order? for a citation of the standard.
Note that if you overload the && operator, the whole expression is equivalent to a function call. In that case both expressions will be evaluated unconditionally (i.e. even if the first expression would be some "falsy" value...).
The order that the operands are evaluated is defined in this case, and it is left-to-right.
This goes for both C and C++.
For a reference of this, see for example page 99 of the C standard: http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf.
Hence, in terms of order-of-evaluation, your code will do what you want it to. But it does have some other problems; see the post comments for this.
Please consider the following block of C++-code.
call * pCall; // Make a pointer to private variable call.
pCall = NULL; // We are sure that it is a null pointer.
aMemberFuntionThatMayChangeTheValueOfpCall();
if (pCall != NULL and pCall->isDelivered() == false){
doSomething();
}
I would like to execute some lines of code, here represented by doSomething(), if and only if pCall is not a null pointer and pCall->isDelivered() is false.
However, I read that the order of evaluation is unspecified. So theoretically the compiler may evaluate pCall->isDelivered() first, and run into a run time exception. However, in the debugging sessions it seems to evaluate the and-operator left to right. Can someone please shine a light on this? I don't want any failures of the code when it gets into a production environment or when it gets executed on another machine.
Of course it is possible to make it into two nested if-statements, but this makes the source far more unreadable because I need this kind of code multiple times.
Can anyone tell me how to do this evaluation in one if-statement such that there is no misevaluation?
Your and operator is more commonly written in C++ as &&, but they are both the same "logical and" operator. For this operator the order of evaluation is specified and evaluation is executed from left to right, guaranteed. (Otherwise millions of existing programs would fail).
The exception - not applicable to your code - is when the && operator is overloaded. In this case the left-to-right rule does not work. BTW it is a main reason why it is recommended not to overload this operator.
Your code below will work (I've changed 'and' to '&&' and added parentheses):
if ( (pCall != NULL) && (pCall->isDelivered() == false) ) {
doSomething();
}
because the logical-AND && will 'short circuit'; i.e. if the first expression is false, the second will not be evaluated. Evaluation order is from left to right in this case.
The following relates to the Miscosoft C++ compiler in VS2013:
Logical operators also guarantee evaluation of their operands from
left to right. However, they evaluate the smallest number of operands
needed to determine the result of the expression. This is called
"short-circuit" evaluation. Thus, some operands of the expression may
not be evaluated. For example, in the expression x && y++ the second
operand, y++, is evaluated only if x is true (nonzero). Thus, y is not
incremented if x is false (0).
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?
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).
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.
The B==2 part is not evaluated.
Be careful! Don't put something like ++B==2 over there!
C++ applies short circuiting to Boolean expression evaluation so, the B == 2 is never evaluated and the compiler may even omit it entirely.
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)
This is short-circuit evaluation, as James says. Lazy evaluation is something entirely different.
No it's not.
Same with &&, if one is wrong, it doesn't bother evaluating the other one.
B == 2 is never evaluated.
See Short-Circuit Evaluation for more information.