This question already has answers here:
Operator Precedence vs Order of Evaluation
(6 answers)
Closed 7 years ago.
I was reading this post
Precedence of && over ||
. It says that even though the precedence of && is more than ||, we need to evaluate the expression from left to right and if the first expression turns out to be true, then we don't need to evaluate the second expression.
But precedence is the order of evaluation and accordingly all pre increments should be evaluated first and then (++j && ++k) should be evaluated. The post seems to be ambiguous on this point. Is it not?
From the standard
§5.14 Logical AND operator
The && operator groups left-to-right. The operands are both contextually converted to bool. The result is true if both operands are true and false otherwise. Unlike &, && guarantees left-to-right evaluation: the second operand is not evaluated if the first operand is false.
The result is a bool. If the second expression is evaluated, every value computation and side effect associated with the first expression is sequenced before every value computation and side effect associated with the second expression.
So, in your example:
(++j && ++k)
The first evaluation will be
++j
Then (assuming j hasn't become 0 and therefore falsey)
++k
Then
j && k // with both values incremented
Related
Many times I see (and sometimes write) code similar to this example:
int a=0, b=2;
if( a && (b=func())!=0 ) {
//...
The question is: does the standard guarantee these statements?
b will be not touched (and remain value 2)
func() will not be called
And vice-versa, if we write if( func()!=0 && a ) - does the standard guarantee func() will be called?
I'm interested in the particular standard paragraph defining this is legitimate.
UPD: my typo, changed from int a=1 to int a=0
To the exact question;
The question is: does standard guarantee these statements?
To the updated question; given a=0. If a==0, then yes, the short circuit evaluation would kick in and func() would not be called; the second operand would not be evaluated.
If a=1 (as it was originally), the opposite; func() will be called - a is 1 thus "true", as a result the second operand is evaluated (it is a logical AND), b will change. If the operator had been || (logical OR), then short circuit evaluation would kick in and func() would not be called.
And vice-versa, if we write if( func()!=0 && a ) -- does standard guarantee func() will be called?
Yes, the first operand is always evaluated.
Yes, short circuit evaluation is guaranteed for C++;
§5.14 Logical AND operator
1 The && operator groups left-to-right. The operands are both contextually converted to bool (Clause 4). The result is true if both operands are true and false otherwise. Unlike &, && guarantees left-to-right evaluation: the second operand is not evaluated if the first operand is false.
2 The result is a bool. If the second expression is evaluated, every value computation and side effect associated with the first expression is sequenced before every value computation and side effect associated with the second expression.
§5.15 Logical OR operator
1 The || operator groups left-to-right. The operands are both contextually converted to bool (Clause 4). It returns true if either of its operands is true, and false otherwise. Unlike |, || guarantees left-to-right evaluation; moreover, the second operand is not evaluated if the first operand evaluates to true.
2 The result is a bool. If the second expression is evaluated, every value computation and side effect associated with the first expression is sequenced before every value computation and side effect associated with the second expression.
The corresponding quotes for C are;
§6.5.13 Logical AND operator
4 Unlike the bitwise binary & operator, the && operator guarantees left-to-right evaluation; if the second operand is evaluated, there is a sequence point between the evaluations of the first and second operands. If the first operand compares equal to 0, the second operand is not evaluated.
§6.5.14 Logical OR operator
4 Unlike the bitwise | operator, the || operator guarantees left-to-right evaluation; if the second operand is evaluated, there is a sequence point between the evaluations of the first and second operands. If the first operand compares unequal to 0, the second operand is not evaluated.
From the C-90 standard.
6.5.13 Logical AND operator
....
4 Unlike the bitwise binary & operator, the && operator guarantees left-to-right evaluation;
there is a sequence point after the evaluation of the first operand. If the first operand
compares equal to 0, the second operand is not evaluated.
Similarly for the Logical OR operator.
The && operator requires both operands to be true. If the first operand evaluates to false, then the second operand will not be evaluated. But beause a is 1, it is considered true and the second expression (operand) is evaluated. Thus func() is called and its result assigned to b and then b is tested to be non-zero.
The standard guarantees that the statements in a sequence of && are evaluated from left to right, and that as soon as one of them evaluates to false, the ones to the right of that will not be evaluated.
The question is: does standard guarantee these statements?
b will be not touched (and remain value 2)
func() will not be called
No, in fact both of them wrong in this case. Because it's operator && so no shortcut logic can be applied in this particular case.
If you change it to || then your statements are correct - only then the evaluation of the first operand (a = 1 in this case) will be enough and the rest is ignored.
As the question changed to a = 0 then yes, both statements are correct and guaranteed.
For C++03, the standard says, that between left and right operand of && operator there is a sequence point, so that all side effects of left operator have taken place before right operator is accessed.
So
int i = 0;
if (++i && i--)
std::cout << i;
is well defined and is guaranteed to output 0.
But what is about this question: is right operand only evaluated if left operand is not 0? It seems to be a detail, but to me the standard guarantees only the sequence point between the operands, not that right operand is never evaluated/accessed in dependence of left one.
E.g.
int arr[10];
int pos; // somehow set to a value from 0 to 10
while (pos < 10 && arr[pos] != 0)
pos++;
Is this well defined? pos could be from begin on 10 or reaches 10. The left operand has no side effects which concur with right operand. Have I the guarantee that arr[10] != 0 is never performed?
Edit:
Thanks to the comments and answers it is clear now:
5.14p2: "The result is a bool. If the second expression is evaluated,
every value computation and side effect associated with the first expression
is sequenced before every value computation and side effect associated with
the second expression."
is the sequence point meaning.
5.14p1: "Unlike &, && guarantees left-to-right evaluation: the second operand is
not evaluated if the first operand is false."
is the short-circuit meaning.
The first without the second would make my example undefined. Thanks.
The standard does guarantee short-circuiting of && and ||.
If the left-hand side of && is false, the right-hand side is not evaluated. For ||, the right-hand side is not evaluated if the left-hand side is true.
5.14p1 of C++11, last sentence:
Unlike &, && guarantees left-to-right evaluation: the second operand is not evaluated if the first operand is false.
So yes, it's guaranteed.
This question already has answers here:
Is Short Circuit Evaluation guaranteed In C++ as it is in Java?
(2 answers)
Closed 9 years ago.
If I write:
if(somePtr != NULL && somePtr->someFun() == SUCCESS )
{
/**/
}
Will it be assured that somePtr != NULL will be checked before somePtr->someFun() == SUCCESS?
Is there any chance that my compiler will reorder these two?
Is there any chance that my compiler will reorder these two?
Nope. It is guaranteed that && evaluates the second expression only if the first one is true (incidentally, it also introduces a sequence point into the whole expression).
The && operator groups left-to-right. The operands are both contextually converted to type bool (Clause 4). The result is true if both operands are true and false otherwise. Unlike &, && guarantees left-to-right evaluation: the second operand is not evaluated if the first operand is false.
The result is a bool. If the second expression is evaluated, every value computation and side effect associated with the first expression is sequenced before every value computation and side effect associated with the second expression.
(C++11, [expr.log.and]; emphasis added)
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Safety concerns about short circuit evaluation
What does the standard say about evaluating && expressions - does it guarantee that evaluation of parameters will stop at the first false?
E.g.:
Foo* p;
//....
if ( p && p->f() )
{
//do something
}
is the f() guaranteed not to be called if p == NULL?
Also, is the order of evaluation guaranteed to be the order of appearence in the clause?
Might the optimizer change something like:
int x;
Foo* p;
//...
if ( p->doSomethingReallyExpensive() && x == 3 )
{
//....
}
to a form where it evaluates x==3 first? Or will it always execute the really expensive function first?
I know that on most compilers (probably all) evaluation stops after the first false is encountered, but what does the standard say about it?
What does the standard say about evaluating && expressions - does it guarantee that evaluation of parameters will stop at the first false?
Yes. That is called short-circuiting.
Also, is the order of evaluation guaranteed to be the order of appearence in the clause?
Yes. From left to right. The operand before which the expression short-circuited doesn't get evaluated.
int a = 0;
int b = 10;
if ( a != 0 && (b=100)) {}
cout << b << endl; //prints 10, not 100
In fact, the above two points are the keypoint in my solution here:
Find maximum of three number in C without using conditional statement and ternary operator
In the ANSI C standard 3.3.13:
Unlike the bitwise binary & operator, the && operator guarantees
left-to-right evaluation; there is a sequence point after the
evaluation of the first operand. If the first operand compares equal
to 0, the second operand is not evaluated.
There is an equivalent statement in the C++ standard
&& (and ||) establish sequence points. So the expression on the left-hand side will get evaluated before the right-hand side. Also, yes, if the left-hand side is false/true (for &&/||), the right-hand side is not evaluated.
What does the standard say about evaluating && expressions - does it guarantee that evaluation of parameters will stop at the first false?
Also, is the order of evaluation guaranteed to be the order of appearence in the clause?
5.14/1. Unlike &, && guarantees left-to-right evaluation: the second operand is not evaluated if the first operand is false.
This only works for the standard && operator, user defined overloads of operator && don't have this guarantee, they behave like regular function call semantics.
Might the optimizer change something like:
if ( p->doSomethingReallyExpensive() && x == 3 )
to a form where it evaluates x==3 first?
An optimizer may decide to evaluate x == 3 first since it is an expression with no side-effects associated if x is not modified by p->doSomethingReallyExpensive(), or even evaluate it after p->doSomethingReallyExpensive() already returned false. However, the visible behavior is guaranteed to be the previously specified: Left to right evaluation and short-circuit. That means that while x == 3 may be evaluated first and return false the implementation still has to evaluate p->doSomethingReallyExpensive().
This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
Is short-circuiting boolean operators mandated in C/C++? And evaluation order?
Is there any defined by standard or math rules order of eveluating boolean sentences? For example:
if (firstTrue && secondTrue)
{
}
can I be sure that firstTrue will be checked first?
Yes. && and || are short circuiting operators. The order of evaluation of operands is well defined (left to right).
&& is also a sequence point.
So writing if( ++i && i) { } is perfectly fine.
ISO C++03 (5.14/1) says:
The && operator groups left-to-right. The operands are both implicitly converted to type bool (clause 4). The result is true if both operands are true and false otherwise. Unlike &, && guarantees left-to-right evaluation: the second operand is not evaluated if the first operand is false.
EDIT: (After seeing the comment)
ISO C++03 (Section 1.9/18) says
In the evaluation of each of the expressions
a && b
a || b
a ? b : c
a , b
using the built-in meaning of the operators in these expressions (5.14, 5.15, 5.16, 5.18), there is a sequence point after the evaluation of the first expression.
Yes firstTrue will be evaluated first. In fact, if firstTrue is false, the secondTrue will not even be evaluated. This is called short circuiting.
Check out this article: http://en.wikipedia.org/wiki/Short-circuit_evaluation
The same happens with ||. If the first argument to || is true, the second will not be evaluated.
It is not about boolean sentences. It is about specific operators in these "sentences" (logical expressions, actually)
The built-in && operator (as well as ||) are special: they guarantee that the left-hand side is evaluated before the right-hand size. They have a sequence point between the LHS and RHS evaluations. And they don't evaluate the RHS if the result is pre-determined by the LHS. Aside from this (and some other operators that have similar sequencing properties), there are no guarantees about the order of evaluation of logical expressions, or any other expressions.
The above applies to built-in && and || operators. Overloaded && and || operators are not special in any way.