0
#include <stdio.h>

int main(void) {
   int d, a = 1 & 0 && (d=4);
   printf("%d\n", d);
   return 0;
}

According to the operator precedence () statement d should be assigned but in the above program logical and is executed first. d value is not assigned to 4. Please anyone help me to understand the above program. I have tried with gcc and some online compilers

ikegami
  • 367,544
  • 15
  • 269
  • 518
Ubendren96
  • 45
  • 4
  • `&&` is short-circuiting. In any case, operator precedence doesn't control order of evaluation. – Mat Apr 18 '20 at 06:40
  • https://stackoverflow.com/questions/39126127/operator-precedence-and-evaluation-order – Mat Apr 18 '20 at 06:42

2 Answers2

2

Let's look at f() + g() * h() first.

Precedence and associativity defines what is an operand of what. For example, C operator precedence and associativity tells us that

f() + g() * h()

means

f() + ( g() * h() )     # * has higher precedence than +

rather than

( f() + g() ) * h()     # If + had higher precedence than *

Notably, precedence doesn't determine the order in which operands are evaluated. In our example, the three functions could be called in any order, as long as the result of g() and the result of h() are multiplied together, and that the result of the multiplication is added to the result of f().


Back to

1 & 0 && ( d = 4 )

Precedence and associativity simply tell us that the above is equivalent to the following:

( 1 & 0 ) && ( d = 4 )    # & has higher precedence than &&

So what does this do?

&& dictates that its right-hand side is only evaluated if its left-hand side is true. This is called short-circuit evaluation or short-circuiting.

1 & 0 is false, so d = 4 is never evaluated. This leaves d unchanged, and thus uninitialized.

ikegami
  • 367,544
  • 15
  • 269
  • 518
  • If I change the statement iintto a = 1 || 1 & 0 && (d = 6) then it will turn into (1 || 1 & 0) && (d=6) now what happens d should be assigned to 6. But again the garbage value is stored in d. – Ubendren96 Apr 18 '20 at 11:20
  • No, it does not stores 6 to d. It agains print garabage value – Ubendren96 Apr 18 '20 at 11:25
  • int main() { int d; int a = 1 || 1 & 0 && (d = 6); printf("%d\n", a); printf("%d\n", d); return 0; } – Ubendren96 Apr 18 '20 at 11:30
  • testprint.c:6:24: warning: '&&' within '||' [-Wlogical-op-parentheses] int a = 1 || 1 & 0 && (d = 6); ~~ ~~~~~~^~~~~~~~~~ testprint.c:6:24: note: place parentheses around the '&&' expression to silence this warning int a = 1 || 1 & 0 && (d = 6); ^ ( ) 1 warning generated. Compiler message no error – Ubendren96 Apr 18 '20 at 11:32
  • `1 || 1 & 0 && (d = 6)` is not equivalent to `(1 || 1 & 0) && (d=6)`, it is equivalent to `1 || ( ( 1 & 0 ) && (d = 6) )`, and we already established that `( 1 & 0 ) && (d = 6)` doesn't evaluate the RHS of the `&&`. – ikegami Apr 18 '20 at 11:33
1
  • 1 & 0 && (d=4) is evaluated like this: (1 & 0) && (d=4)
  • (1 & 0) is 0
  • because of short circuiting the right hand side of the && operator is not evaluated
  • therefore d=4 is never evaluated
  • therefore d is never assigned
  • and therefore d contains garbage because local variables are not initialized

If you change int d to int d = 42, the output of your program will be 42

Jabberwocky
  • 48,281
  • 17
  • 65
  • 115