2

In the code below:

#include <stdio.h>

int main()
{
     int a = 1;
     int b = 1;
     int c = a || --b;
     int d = a-- && --b;
     printf("a = %d, b = %d, c = %d, d = %d", a, b, c, d);
     return 0;
}

i was expecting the output to be:

a=0,b=1,c=1,d=0

because due to short circuiting in the line below, ie a-- returns 0 so the other part wont get executed right?

int d = a-- && --b;

The output is:

a = 0, b = 0, c = 1, d = 0

can anyone please explain?

Shafik Yaghmour
  • 154,301
  • 39
  • 440
  • 740
san45
  • 459
  • 1
  • 6
  • 15
  • 1
    `a--` evaluates to `a`, in this case `1` and then decrements `a`. – godel9 Oct 26 '13 at 12:18
  • [Why does `++x || ++y && ++z` calculate `++x` first, even though operator `&&` has higher precedence than `||`](https://stackoverflow.com/q/3700352/995714) – phuclv Aug 18 '18 at 11:24

6 Answers6

5

In first case

int c = a || --b;  

After this a=1 , b=1 and c=1

a value is 1 , because of short circuit evaluation --b did not performed

int d = a-- && --b;

a-- is post decrement so decrement of a won't effect in expression where as --b is pre decrement so effects here

Your condition becomes

   int d= 1 && 0 ; 

After this a=0; , b=0,c=1 and d=0.

Gangadhar
  • 10,248
  • 3
  • 31
  • 50
4

In the first or operation, --b is not executed since a equals 1:

int c = a || --b;

But b is decremented here:

int d = a-- && --b;

Because a equals 1 and is decremented after it is evaluated (a-- equals 1). In other words, this line is similar to:

int d = 1 && --b;

b was equal to 1 so now b equals 0 now. And d also equals 0 because --b returns 0.

Maxime Chéramy
  • 17,761
  • 8
  • 54
  • 75
4
int c = a || --b;

In this line, the C standard requires the C implementation to evaluate a first and, if it is not zero, not to evaluate --b. Although -- has higher precedence than ||, that just means that -- is grouped with b for the purposes of determining the structure of the expression, not for purposes of evaluating it. The left side of an || operator must be evaluated before the right side and, if the left side is true, the right side must not be evaluated, even in part.

So, after the above, b is not changed; it is still 1.

int d = a-- && --b;

As with ||, the left-hand side of the && is evaluated first. So a-- is evaluated. This changes a to 0. However, the value of a-- is a before the change, so it is 1. A value of 0 would prevent the right side from being evaluated (because, once we know the left side is zero, we know the value of the complete && expression is zero). But, since the left side is not zero, --b must be evaluated to finish the &&. This changes b to 0. “Short-circuiting” means the left side is evaluated first, but the right side is still evaluated when necessary.

Eric Postpischil
  • 195,579
  • 13
  • 168
  • 312
  • Yeah - when i had posted my answer - i completely overlooked the fact that there are sequence points `Between evaluation of the left and right operands of the && (logical AND), || (logical OR) (as part of short-circuit evaluation), and comma operators` – Sadique Oct 26 '13 at 13:13
2

the line below, ie a-- returns 0

No, it doesn't. It yields 1, as the post-decrement operator evaluates to the unmodified value of the variable. What you are thinking about is perhaps --a.

1

c = a || --b

so at first a is evaluated and a value is 1 which is true. So compiler does not evaluate --b. So b value is still 1

Now

d = a-- && --b

a-- && --b => 1 && 0 (since --b = 0 ) since b value is at 1.

why 1 because a-- is post decrement operator

Why 0 because --b is pre decrement operator

so 1 && 0 returns 0 and this value is stored in d

So the output: a = 0, b = 0, c = 1, d = 0

Grijesh Chauhan
  • 57,103
  • 20
  • 141
  • 208
niko
  • 9,285
  • 27
  • 84
  • 131
  • There is no associativity here. Left-to-right associativity means that `a || b || c` is grouped as `(a || b) || c`. It does not mean `a` is evaluated before `b`. That is a separate rule. – Eric Postpischil Oct 26 '13 at 12:38
-2

You're mixing up a-- with --a. The result of the expression a-- is a before the decrement, while --a is a after the decrement; in other words:

int a = 1;
int b = a--; // b == a == 1
int c = --b; // c == b-1 == 0

As a result, you have:

int d = a-- && --b;
// =>   1   && b-1
// =>   1   && 0
// =>   0
Tim Čas
  • 10,501
  • 3
  • 26
  • 32