4

The code snippet is:

int main()
{
     int a = 1, b = 2, c = 3;
     printf("%d", a += (a += 3, 5, a));
}

Though it displays 8 in the terminal as an output. But am not getting the concept behind it.

haccks
  • 104,019
  • 25
  • 176
  • 264
Devinder Kaur
  • 53
  • 1
  • 1
  • 4

3 Answers3

10

The expression a += (a += 3, 5, a) will invoke undefined behavior.

C standard says

C11: 6.5.16 Assignment operators (p3):

[...] The side effect of updating the stored value of the left operand is sequenced after the value computations of the left and right operands. The evaluations of the operands are unsequenced.

It is not guaranteed that whether the left most a will be evaluated before or after the evaluation of (a += 3, 5, a). That will result in undefined behavior.

haccks
  • 104,019
  • 25
  • 176
  • 264
  • 2
    actually you are confusing the comma separator (used for separation of function parameters) with the comma operator (which is actually sequenced) ... OP case is NOT undefined behaviour, although at first glance it may seem so ... in this particular case, the left most a in the parentheses will be evaluated BEFORE the right most a. For further detail. http://en.wikipedia.org/wiki/Comma_operator – Ahmed Masud Jun 03 '15 at 17:57
  • @AhmedMasud; I read that wiki article many times. You need to read that again and thanks for your downvote. – haccks Jun 03 '15 at 17:58
  • 3
    The ambiguity isn't a result of the comma operator, but rather in the final assignment of `a`. It's equivalent to `a += (a += 3)` which has undefined behavior according to the part of the standard haccks quoted – Sean Jun 03 '15 at 18:01
  • 1
    @Sean this is subtly different from the OP statement. The comma operator has the *lowest* precedence of all operators. which forces a+=3 to be evaluated before 5 and before the second a ... which forces the sequence.. a+= (a+=3) is undefined YES; and a+=(5, a+=3) is undefined (I'm not quite sure whether yet, it may not be have to check); however a+=(a+=3, 5) is not undefined, the comma operator acts an explicit sequence point -- which guarantees that any side effects of a+=3 inside the parenthesis would have been performed BEFORE 5 is evaluated. – Ahmed Masud Jun 03 '15 at 18:11
  • @AhmedMasud; Comma operator guarantees the evaluation `a += 3` before `5` but it doesn't guarantee the evaluation of left most `a` before the evaluation of `(a+=3, 5)`. – haccks Jun 03 '15 at 18:16
  • actually it does, since comma operator is a sequence point, it DOES guarantee all side effects of the expression before it to be evaluated PRIOR to 5 being touched. – Ahmed Masud Jun 03 '15 at 18:25
  • interesting, i see what you mean. i think you're correct – Sean Jun 03 '15 at 18:29
  • some relevant discussion [here](http://stackoverflow.com/questions/4176328/undefined-behavior-and-sequence-points), notably an example given: `i = (++i,i++,i) // well defined ` – Sean Jun 03 '15 at 18:32
  • @Sean; Yes `i = (++i,i++,i)` is well defined, but is `i += (++i,i++,i)` also well defined? Think over it. Standard says: *If a side effect on a scalar object is unsequenced relative to either a different side effect on the same scalar object or a value computation using the value of the same scalar object, the behavior is undefined.* (C11: 6.5 Expressions). – haccks Jun 03 '15 at 18:37
  • @haccks it follows from the same reason that `i = (++i, i)` is well defined, doesn't it? before the `+=` operator is evaluated, the comma sequence point ensures that all side effects from `++i` are complete. it appears to me that `i = (++i, i);` is equivalent to `++i; i = i;` and that `i += (++i, i);` is equivalent to `++i; i += i;` – Sean Jun 03 '15 at 18:42
  • @Sean; No. `i += (++i, i)` is **not equivalent to** `++i; i += i`. I quoted the standard in my last comment. – haccks Jun 03 '15 at 18:43
  • @haccks yes, yes, thinking about it more i think you're right again. i've flip-flopped on this about three times now :). similarly, `i = i + (++i, i);` is undefined, yes? – Sean Jun 03 '15 at 18:54
  • actually i stand corrected, haacks is right... I kinda screwed up my own thinking here ... – Ahmed Masud Jun 03 '15 at 18:54
  • @Sean; Yes exactly. Thank you. – haccks Jun 03 '15 at 18:59
  • 1
    To fix my own thinking, I broke the thing down on paper as following stack based machine where oder of push in not garanteed... So Example: a = 7; a = a + (a = 7+3, 5, a)... If order is push a (7); push a(7) ; add 3 ; assign a(10) ; push 5; pop 5; push a; add ; assign a ... then a = 17 ; however if order is push a(7) add 3; assign a(10); push 5; pop 5; push a (10); push a(10) ; add ; assign... then a = 20 ;; thus the undefined behavior – Ahmed Masud Jun 03 '15 at 19:02
6

This is an effect how the comma operator works, the last element is the one that is used as the value of the statement. So essentially what you got here is the following:

a += (a += 3, 5, a)

This evaluates a+=3 first, this makes a=4 this result is discarded, then evaluate 5 then this result is discarded, then evaluate a and keep this as it's the last item. The result from (a += 3, 5, a) is the last item which is a which is 4.

Then you get

a += 4

so a is 8.

Important Note: that this is an artifact of how your compiler has generated the code. The C standard doesn't guarantee the order of execution for the assignment to a in this situation. See haccks answer for more information about that.

shuttle87
  • 15,466
  • 11
  • 77
  • 106
  • 4
    Good except minor correction: the result from `(a += 3, 5, a)` is the _last_ item, though here the result is the same (`a`) – Sean Jun 03 '15 at 17:48
  • I.E. the 5 has absolutely no effect on what is printed – user3629249 Jun 03 '15 at 17:54
  • @user3629249, the 5 is completely superfluous here. – shuttle87 Jun 03 '15 at 18:00
  • your latest edit is incorrect, the comma operator must be evaluated left-to-right. – Sean Jun 03 '15 at 18:02
  • @Sean, indeed, I was too hasty with the previous edit. As far as I can tell the only 2 possible outcomes for this would be a = 8 and a = 2 depending on the order in which the assignment to a happened. – shuttle87 Jun 03 '15 at 18:10
-1

As we know that comma has lowest precedence as operator so in, a + = (a + = 3, 5, a) in this what will happen is first evaluation will be like this a+3 = 4 but then it will be discarded now evalutation will be a+5 = 6 now in third step we have to do a+a right so here answer will be value from previous operation i.e. 6 and then 6+1 = 7 now we will come out of the brackets and we will do a = a+ 7 which is a = 1 + 7 so answer will be 8 so therefore (a += 3,5,a) will get you 7 and a = a + 7 will get you 8 which will be printed finally

Ruben Helsloot
  • 12,582
  • 6
  • 26
  • 49
  • Please try to improve your answer. I tried to improve the grammar, but got lost in the chaos. I'd be happy to retract my downvote then. See also [answer] – Ruben Helsloot Dec 08 '20 at 23:05