16

Why the output of below mentioned program is 0 not 20 ?

#include <stdio.h>

int main()
{
    int i = 10, j = 0;
    if (i || (j = i + 10))
       /* do something */;                
    printf("%d\n",j);
}
Soner Gönül
  • 97,193
  • 102
  • 206
  • 364
duslabo
  • 1,487
  • 4
  • 20
  • 33
  • 21
    Short circuited boolean expression. – jxh Jul 19 '13 at 08:01
  • 1
    This may seem like a silly question but I'm learning - how could the program ever output 20? Is it something to do with C specifically? – Andy Jul 19 '13 at 16:36
  • 1
    @Andy **(1)**--program could output `20`, only if `i = 0` (that give change to execute expression `j = i + 10`). **(2)** No, this code is valid in C++, even in Java because in both we can do `=` within `if()` and both support short-circuit. --- It would be interesting to know even [Python supports short-circuit](http://stackoverflow.com/questions/2580136/does-python-support-short-circuiting/14892812#14892812) but this expression `if (i || (j = i + 10))` is not valid in Python because `=` in `if` is syntax error. – Grijesh Chauhan Jul 19 '13 at 16:43
  • @GrijeshChauhan Thanks for that! I thought that would be the case but I was just a little confused by the fact `i` is hard coded to equal 10 – Andy Jul 19 '13 at 16:48
  • 1
    @Andy yes, and you know na **?** that any `non-0` value is `true` in C and so `i` (=10) is `ture`. – Grijesh Chauhan Jul 19 '13 at 16:53
  • Hello, This is first time I am getting this much response for my question. It makes difficult to accept the answer, sorry for changing 3 times. :) Thanks Paul and Grijesh :) – duslabo Jul 19 '13 at 17:02
  • 1
    @JeshwanthKumarNK I added in my answer that `||` and `&&` operators introduces sequence point so `++i || ++i` is not a undefined behaviour :) whereas `++i | ++i` is Undefined :( . got it? – Grijesh Chauhan Jul 25 '13 at 09:17
  • @GrijeshChauhan Just tested :) Ya you are right :) I got it :) Thanks – duslabo Jul 26 '13 at 17:16

4 Answers4

27

Yes, the concept is called Short-Circuit (in logical &&, || operators expression).

In the case of any logical expression (includes ||, &&) compiler stop evaluation expression as soon as result evaluated (and save executions).

The technique for short-circuit is:

!0 || any_expression == 1, so any_expression not need to evaluate.

And because in your expression i is not zero but its 10, so you can think if consdition (i || (j = i + 10)) just as i.

Logical OR 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 unequal to 0, the second operand is not evaluated.

Similarly for && (and operator):
0 && any_expression == 0, so any_expression not need to evaluate.

In your expression:

(i || (j = i + 10) )
      ------------
       ^
       | Could evaluate if i is 0, 
       as i = 10 (!0 = true), so j remains unchanged as second operand is not evaluated

For or || operator answer can be either 0, 1. To save execution, evaluation stops as soon as results find. So if first operand is non-zero result will be 1 (as above) for the expression. So for first operand i = 10 compares unequal to 0, the second operand (j = i + 10) is not evaluated so j remains 0 hence output of your code is 0.

Note: Short-circuit behavior is not only in present in C but concept is common to many languages like Java, C++, Python. (but not all e.g. VB6).

In C short-circuiting of logical expressions is guaranteed has always been a feature of C. It was true when Dennis Ritchie designed and implemented the first version of C, still true in the 1989 C standard, and remains true in the C99 standard.

A related post: Is short-circuiting boolean operators mandated in C/C++? And evaluation order?

Community
  • 1
  • 1
Grijesh Chauhan
  • 57,103
  • 20
  • 141
  • 208
  • 9
    Honestly, far too long answer. – Antonio Jul 19 '13 at 08:28
  • 9
    *"In the case of any logical expression most compiler stop evaluation expression as soon as result evaluated (to save executions)."* - No, it isn't done by *"most compilers"*, but by *all* that call themselves C compilers, because it is mandated by the standard. So more often than not this isn't just for the sake of performance but correctness, e.g. think about `while(node && node->value)`, which would be terribly wrong if the standard didn't *guarantee* short-cirtuiting. – Christian Rau Jul 19 '13 at 09:42
  • 1
    @ChristianRau I disagree with you. Original purpose of short-circuit to get performance. And I perfectly understand `while(node && node->value)` its second benefit of short-circuit. – Grijesh Chauhan Jul 19 '13 at 09:46
  • 7
    @GrijeshChauhan You might disagree with that (only the standard comitte can answer that and you might very well be correct about the original purpose). You can however in absolutely no way disagree with the fact that not *"most compilers"* do this, but *all*. A compiler that doesn't do this is not a C compiler and it would be just like something like `=` or `+` wouldn't work as expected, you cannot rely on any code to work with such a compiler. As it stands you answer sounds like this is just a compiler implementation optimization, which is *not* the case. – Christian Rau Jul 19 '13 at 09:51
  • 1
    @Grijesh: you should clarify the part in your answer about "most compilers" because at present it sounds like you're suggesting that not all C compilers adhere to the C language standard in this regard. It's confusing at best - you should probably limit the scope of the answer to C. – Paul R Jul 19 '13 at 10:04
  • 4
    @Grijesh: you just need to clarify that sentence so that people don't get the wrong idea when they read your answer. You can see that already two people have misunderstood your answer. One of the great thing about SO is that answers can always be *improved*. – Paul R Jul 19 '13 at 10:14
  • 1
    @PaulR that is the way one should write comment. Thanks I appreciate it. and I try to improve my answer. – Grijesh Chauhan Jul 19 '13 at 10:16
  • 1
    Thanks, yes, that has removed the ambiguity - down-vote now converted to up-vote. – Paul R Jul 19 '13 at 10:55
  • 2
    Thank you, it isn't misleading anymore, +2. – Christian Rau Jul 19 '13 at 11:22
  • 1
    *"Please take time before down-vote."* - I *took* time to read and understand the answer before downvoting. I even took the time to repeatedly clarify my problems with the answer in clear, objective and constructive comments. I'm glad things are finally sorted out now. – Christian Rau Jul 19 '13 at 11:27
  • @JeshwanthKumarNK hey Jeshwanth! my old answer was even correct Parul R. and christianRau was just helping me to remove ambiguity/a confusing statement in old version answer. Please feel free to accept any answer you wants. And if you have any doubt left let us know. – Grijesh Chauhan Jul 19 '13 at 17:02
20

|| is a short-circuit operator - if the left hand side evaluates to true then the right hand side does not need to be evaluated. So, in your case, since i is true then the expression j = i + 10 is not evaluated. If you set i to 0 however then the right hand side will be evaluated,

Paul R
  • 208,748
  • 37
  • 389
  • 560
5

In if (i || (j = i + 10)), there are two boolean expression to evaluate. The thing is, the first one is true, therefore there is no need to compute the second. It's purely ignored.

johan d
  • 2,798
  • 18
  • 26
3

because || is a short-circuit operator (so is the && operator).

so in (i || j = i+10), i is 10, left part of || is true, the expression j = i+10 didn't happen, as a result, j=0.

J. Steen
  • 15,470
  • 15
  • 56
  • 63
tczf
  • 85
  • 1
  • 6