问题
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 value2
)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
回答1:
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 guaranteefunc()
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.
回答2:
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.
回答3:
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.
回答4:
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.
回答5:
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.
来源:https://stackoverflow.com/questions/35912322/c-and-c-operand-resolution-order