I have a if block as below in C++:
if( node != NULL && node->next !=NULL ){
//do some stuff
}
Can anybody tell me do I need to split node and node->next in two if block? or is it
guaranteed that node!=NULL will executed before node->next!=NULL ?
This is a short circuit evaluation and the operator && guarantees that the left-hand side expression will be fully evaluated before the right-hand side is evaluated
From the standards:
5.14 Logical AND operator [expr.log.and]
logical-and-expression:
inclusive-or-expression
logical-and-expression && inclusive-or-expression
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.
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.
No, you do not. The && operator short-circuits; if the left operand evaluates to false then the right operand is not evaluated at all, because the result is already known. (Similarly, the || operator will not evaluate the right operand when the left operand is true.)
You do not need to. node!=NULL will execute first and if it is false it will not evaluate the rest of the conditions.
If the first condition is false then the second condition will not be evaluated because in any case the full expression will be equal to false independing on what is the result of evaluatuin of the second condition.
According to the C++ Standard
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.
Related
Does SystemVerilog evaluate the whole if statement or the minimum to get the result?
For example:
if (condition1 && condition2) begin
...
end
if (condition1 || condition2) begin
...
end
In the first case, will condition2 be evaluated if condition1 is False?
In the second case, will condition2 be evaluated if condition1 is True?
This behavior is also known as short-circuit evaluation.
Refer to IEEE 1800-2017, section 11.4.7 Logical operators.
The && and || operators shall use short circuit evaluation as follows:
— The first operand expression shall always be evaluated.
— For &&, if the first operand value is logically false then the second
operand shall not be evaluated.
— For ||, if the first operand value is logically true then the second
operand shall not be evaluated.
Therefore, for the operators in your if statements, all the expressions may not be evaluated.
To see which operators have similar behavior, and which do not, refer to section 11.3.5 Operator expression short circuiting.
This question already has answers here:
Is short-circuiting logical operators mandated? And evaluation order?
(7 answers)
Closed 3 years ago.
I always dare NOT to code like this:
void func( some_struct* ptr ) {
if ( ptr != nullptr && ptr->errorno == 0 )
do something...
};
instead I always do like this:
void func( some_struct* ptr ) {
if ( ptr != nullptr )
if ( ptr->errorno == 0 )
do something...
};
because I'm afraid that the evaluation order of logical operator && is un-specified in C++ standard, even though commonly we could get right results with almost all of nowdays compilers.
In a book, 2 rules let me want to get known exactly about it.
My question is :
Without overloading, is the evaluation order of logical operator "&&" and "||" definite?
Sorry about my ugly English, I'm a Chinese. and I apologize if there is a duplicated topic, because I can't finger out correct key-words to search with.
Thanks anyway!
Yes, it's guaranteed for built-in logical AND operator and logical OR operator by the standard.
(emphasis mine)
[expr.log.and]/1
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.
[expr.log.or]/1
The || operator groups left-to-right. The operands are both contextually converted to bool. The result is 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.
Evaluation order for && and || is left to right.
Means in this case if (condition-1 && condition-2), then compiler will first check condition-1. If condition-1 is true then it will go to check next condition. But if condition-1 if false. It will return false as in && one false condition means result is false
Sameway in case of if (condition-1 || condition-2), compiler will first check condition-1. If it is true then it will return true. Because if ||, if one condition is true, then result is true. No need to check next conditions. But if it is false it will check next condition...
Those operators have fixed evaluation rules that you can rely on.
You can safely use code like this:
if (op1 && op2)
With &&, both operands are needed to result to true in order for it to be true, if one of them is false then it short circuits, meaning that further evaluation of the && stops and it returns false. In short words, if the first operand is false then the second operand will not be evaluated since the operator will return false immediately.
For the case of || it will short circuit if at least one of its operands its true. Therefore, if the first operand is true then it will not evaluate the second operand because the operator returns true automatically.
This means that code like this: if (op1 && op2) is equivalent to:
if (op1)
{
if (op2)
{
//some code
}
}
And code like this if (op1 || op2) is the same as:
if (op1)
{
//some code
}
else if (op2)
{
//same code
}
Check these to know more about order of evaluation, operator precedence and logical operators.
I have a simple condition that looks like this :
if (k==0 && f())
f has side effects and must not be called if k is different from 0. Can I rely on boolean short-circuits so that the compiler never calls f ? Of course, I could haved moved the if to the outside to guarantee f is never called when k != 0, but this is shorter.
8.14 Logical AND operator [expr.log.and]
The && operator groups left-to-right. The operands are both contextually converted to bool (Clause 7). 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.
So, if k is not equal to 0, a conformant compiler will not call f.
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.
Pre-C++11 we know that short-circuiting and evaluation order are required for operator && because of:
1.9.18
In the evaluation of the following expressions
a && b
a || b
a ? b : c
a , b
using the built-in meaning of the operators in these expressions, there is a sequence point after the evaluation of the first expression (12).
But sequence points no longer exist in C++11, so where is the standard part that says:
if (ptr && ptr->do_something())
{
}
is safe?
[expr.log.and]
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.
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.