4
#include <stdio.h>

int main(void)
{ 
   int a = 0, b = 1;
   a = (a = 5) && (b = 0);
   printf("%d", a);
   printf("%d", b);
}

The value of variable a is getting updated twice, which violates the C standards. So I think it will be compiler dependent. My I ran this code in lot of online C compilers and all are giving same output.

chqrlie
  • 131,814
  • 10
  • 121
  • 189

1 Answers1

8

The behavior of this code is well defined due to the sequence point introduced by the && operator. This is spelled out in section 6.5.13p4 of the C standard regarding the logical AND operator &&:

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.

Going through the code:

a = (a = 5) && (b = 0);

The left side of the && operator, i.e. (a = 5) is evaluated first, which sets a to 5. This evaluates to true, so there is then a sequence point before the right side, i.e. (b = 0) is evaluated. This sets b to 0 and evaluates to false, so the && operator results in the value 0. This value is then assigned to a.

dbush
  • 205,898
  • 23
  • 218
  • 273
  • So && operator automatically introduces a sequence point ? I thought semi-colon is the only sequence point. Kindly explain other sequence points too – SUBHAJIT PAUL Jun 08 '23 at 15:28
  • @SUBHAJITPAUL That's a separate question, and one that's too broad for this site. – dbush Jun 08 '23 at 15:32
  • 5
    It has to be a sequence point because the left side has to be evaluated first to decide whether or not to evaluate the right side -- it's called short-circuiting. – Blindy Jun 08 '23 at 15:32
  • @SUBHAJITPAUL Take a look here: https://en.cppreference.com/w/c/language/eval_order – nielsen Jun 08 '23 at 15:32
  • Thanks a lot @nielsen – SUBHAJIT PAUL Jun 08 '23 at 15:49
  • 1
    Although `a = (a = 5) && (b = 0);` is well defined, `a = (a = 0) && (b = 5);` will result in UB! – Ian Abbott Jun 08 '23 at 16:07
  • ... However, `a = (a = 0) && (b = 5);` is well-defined in C++ even though it is UB in C. C++ sequences the side-effect of the assignment before the value computation of the assignment expression. – Ian Abbott Jun 08 '23 at 16:27
  • @nielsen Although https://en.cppreference.com/w/c/language/eval_order fails to mention that the sequence point between the first and second operands of `&&` or `||` is conditional on the second operand being evaluated. If the second operand is not evaluated then the sequence point before it is skipped. – Ian Abbott Jun 08 '23 at 16:39
  • 1
    @IanAbbott Of course something that is not evaluated cannot be on one side of a sequence point, but doesn't there still have to be a sequence point between the first operand and whatever is evaluated afterwards? The first operand has to be evaluated to decide whether or not the second operand must be evaluated and that has to be done in such a way that there is a sequence point afterwards in case the second operand must be evaluated. – nielsen Jun 08 '23 at 18:43
  • 3
    @IanAbbott -- a reference to the spec may be helpful: [...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.](http://port70.net/~nsz/c/c11/n1570.html#6.5.13) – ad absurdum Jun 08 '23 at 19:05