1

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?

  1. b will be not touched (and remain value 2)
  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

Galimov Albert
  • 7,269
  • 1
  • 24
  • 50
  • 1
    in this situation func will be called guaranteed, because a = 1 – nikniknik2016 Mar 10 '16 at 09:29
  • 4
    Why would `a && (b=func())!=0` short circuit when a is 1? – Neil Mar 10 '16 at 09:30
  • 1
    Also note that you shouldn't write code like this; keep it simple and "stupid". – August Karlstrom Mar 10 '16 at 09:35
  • To me, the question would make more sense if the condition were `a ||(b=func()) != 0` since this would actually be a case for short-circuit evaluation. – anderas Mar 10 '16 at 09:36
  • I would put it a bit stronger than @AugustKarlstrom - this is very bad code indeed and the author should be fired or given a '-F' grade. – Martin James Mar 10 '16 at 11:12
  • @MartinJames wow, wow, easy. In such strict mode you can get 0 workers in your team and then get fired=) Its not "black and white" world and you can see similar code almost everywhere. That was trigger for this question. – Galimov Albert Mar 10 '16 at 11:25

5 Answers5

4

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.

Community
  • 1
  • 1
Rishikesh Raje
  • 8,556
  • 2
  • 16
  • 31
4

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.

Niall
  • 30,036
  • 10
  • 99
  • 142
  • 1
    Yes that's how short circuit works - but isn't that the two statements in the question are completely wrong here - given `a = 1` ? – artm Mar 10 '16 at 09:40
  • @artm. Yes, given the values in the question, `func()` will be called in the first place and in the vice-versa case. – Niall Mar 10 '16 at 09:45
  • @artm. Don't know either (given the data in the question), maybe add a note that this is because of the data in the question and not something inherent in the && operator. – Niall Mar 10 '16 at 09:58
  • Sorry my bad about first case, i meant when `a==0` – Galimov Albert Mar 10 '16 at 10:05
  • @PSIAlt. If `a==0`, then yes, the short circuit evaluation would kick in and `func()` would not be called. – Niall Mar 10 '16 at 10:06
2

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.

Niall
  • 30,036
  • 10
  • 99
  • 142
Sven Nilsson
  • 1,861
  • 10
  • 11
2

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.

Paul Ogilvie
  • 25,048
  • 4
  • 23
  • 41
-1

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.

Community
  • 1
  • 1
artm
  • 17,291
  • 6
  • 38
  • 54
  • 1
    No, it doesn't - and that is exactly the point. If the first operand evaluates to 0, you do not need to evaluate the second, because the expression can no longer evaluate to true. – tofro Mar 10 '16 at 09:48
  • 1
    @tofro - the first operand is `a` which is `1` NOT `0` in the question - so the 2nd operand must be evaluated. – artm Mar 10 '16 at 09:53
  • 1
    My comment refers to the statement "the logic operator && requires ALL operands to be evaluated" - Which is generally NOT true and shouldn't be stated like that. – tofro Mar 10 '16 at 10:02
  • @tofro ah now I see, I was focusing on the this particular problem - agree and edited - thanks. – artm Mar 10 '16 at 10:06