-10

Please give a detail explanation of how (a+=3,5,a) is evaluated in the following program.

#include <stdio.h>
int main()
{
    int a=1,b=2,c=3;
    printf("%d\n",a+=(a+=3,5,a));
}
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
  • I'm actually curious to know what `(a+=3,5,a)` is and how it works. Sure the output is 8 and I can understand why, but why don't the `,5,a` part throw errors. – cs95 Aug 05 '17 at 06:29
  • It does compile and outputs `8`. – Weather Vane Aug 05 '17 at 06:29
  • @WeatherVane yess – Tanuj Yadav Aug 05 '17 at 06:32
  • I had just deleted a remark which said the code has *undefined behaviour* because `a` is amended twice in the same expression without a sequence point. – Weather Vane Aug 05 '17 at 06:34
  • @cᴏʟᴅsᴘᴇᴇᴅ: The `(a += 3, 5, a)` is a comma expression; it's valid and, on its own, causes no trouble. There are sequence points between the three terms. The `, 5` does nothing useful. There's room to argue that `(a += 3, a)` imposes a sequence point on operations, but there are no circumstances I can think of where you could legitimately need that. Because this code uses `a += (a += 3, 5, a)`, it is undefined behaviour because although there are sequence points in the RHS expression, there isn't a sequence point between the evaluation of the LHS and RHS of the overall expression. – Jonathan Leffler Aug 05 '17 at 07:00
  • @JonathanLeffler Correct me if I'm wrong. `a += 3` is evaluated first, followed by 5, and then `a`, and then the resultant expression is `a` (clearly not `a += 3`, but `a`!)? You then get `a += a` which is UB, am I understanding this right? – cs95 Aug 05 '17 at 07:05
  • Note that `a+=(a+=3,5,a)` is actually `a=a+(a+=3,5,a)` which makes the UB more clearly seen. – Weather Vane Aug 05 '17 at 07:06
  • @cᴏʟᴅsᴘᴇᴇᴅ: You can't tell whether the `a` on the LHS of the first `+=` is evaluated before or after the expression on the RHS. So it is UB. – Jonathan Leffler Aug 05 '17 at 07:10
  • Thanks. I've got it now. – cs95 Aug 05 '17 at 07:14

4 Answers4

1

In the following code, b and c are evaluated and the last value is added to a and assigned to d.

#include <stdio.h>

int main(void)
{
    int a = 1, b = 2, c = 3, d;
    d = a + (b, c);
    printf("%d\n", d);
    return 0;
}

Program output: 4

But the expression in the question has undefined behaviour since a is being altered more than once without a sequence point.

Weather Vane
  • 33,872
  • 7
  • 36
  • 56
  • My initial reaction was "dup of [Why are these constructs undefined behaviour](http://stackoverflow.com/questions/949433/why-are-these-constructs-undefined-behavior)" but the commas in the `(a += 3, 5, a)` impose sequence points, so there are sequence points in there. I suppose the issue is whether the evaluation of the LHS of `a += (a += 3, 5, a)` is properly sequenced with the RHS; the RHS on its own is OK. ...Grrrr...I now think my first instinct was correct (but I've blown it now by undoing my closure as a dup). – Jonathan Leffler Aug 05 '17 at 06:45
  • @JonathanLeffler I was unsure so I had deleted my first comment to that effect, but reinstated it when someone had replied, and stuck to my assertion. Even if not really true, the code is too horrible to use in real life. – Weather Vane Aug 05 '17 at 06:46
  • Tricky, tricky, tricky — but I think _undefined behaviour_ is the correct diagnosis. – Jonathan Leffler Aug 05 '17 at 06:48
  • @JonathanLeffler the question was about what happens when a comma operator is present, so not an exact dup. – Weather Vane Aug 05 '17 at 06:51
  • The text of the question is about `(a += 3, 5, a)` which is easy and well defined. The code of the question is about `a += (a += 3, 5, a)` which is tricky and undefined behaviour. If it was `b += (a += 3, 5, a)` then everything would be kosher. I wonder why `b` and `c` are in the question at all; they're unused variables. The `, 5` part is mysterious and pointless too, and when that's eliminated, the `, a` part is pointless too — except that it forces a sequence point. So much confusion in so little code! – Jonathan Leffler Aug 05 '17 at 06:53
1

The code under consideration is, when modernized and given some missing spaces:

#include <stdio.h>
int main(void)
{
    int a = 1, b = 2, c = 3;
    printf("%d\n", a += (a += 3, 5, a));
    return 0;
}

My initial reaction was "dup of Why are these constructs undefined behaviour", even though that is primarily about ++ and -- operators which are more often seen in such questions.

A second glance notes that there a comma operators in (a += 3, 5, a) and these impose sequence points. On its own, this much of the expression is fine. If it were used in b += (a += 3, 5, a), there would be no problem. The text of the question asks about just (a += 3, 5, a).

Of course, the , 5 does nothing useful. And when that's eliminated, the only reason to use (a += 3, a) is to put a sequence point between the addition and the a. However, there are no circumstances I can think of where you could legitimately need that sequence point.

The more complex issue is whether the evaluation of the LHS of a += (a += 3, 5, a) is properly sequenced with the RHS. It is undefined behaviour because although there are sequence points in the RHS expression, there isn't a sequence point between the evaluation of the LHS and RHS of the overall expression.

Remember that the compound assignment operator += behaves more or less as:

a += x;
a = a + x;

The difference is that the expression on the LHS (a in this example) is only evaluated once. In this case, there's no problem. If the code were more complex, this detail matters:

array[index++].member[subindex++] += 23;

Now it is crucial that the LHS is only evaluated once!

Summary

The code in the question is tricky code and, because it has undefined behaviour, it should be avoided in production code.

I wonder why b and c are in the question at all; they're unused variables. So much confusion in so little code!


Rule of thumb: Avoid multiple increments, decrements and compound assignment operators in a single expression.

Advanced rule of thumb (for experts only): don't apply multiple increments, decrements or compound assignment operators to the same variable in a single expression.

If you know enough to know when you can safely break the rules (?:), then you don't necessarily need to follow the rules of thumb. Until then, avoid over-using these operators.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
  • It was asked in an interview.I gave the right answer but failed to give the explanation properly.Also the hiring manager said one should know what code to not write. – noobwithskills Aug 05 '17 at 09:04
-1

Execution of printf in c is from right to left.

(a+=3,5,a), makes a=4
Then a+=(a+=3,5,a) add the last value i.e a to a
Thatswhy a becomes 8.

Tanuj Yadav
  • 1,259
  • 13
  • 21
  • I understand that a=4, but what is the contribution of ,5,a) here? – Shankhadeep Mukerji Aug 05 '17 at 06:36
  • 1
    There's no guarantee that the LHS of `a += (a += 3, 5, a)` is evalauted before or after the comma expression on the RHS, so the result is _undefined behaviour_. There is no general rule of 'argument evaluation is from right to left — or from left to right'. The order of evaluation is undefined. – Jonathan Leffler Aug 05 '17 at 06:50
  • 1
    @ShankhadeepMukerji out of (a+=3,5,a), a will be added to whatever is on left side. And 5 is useless, This code is too horrible to be used in real life. – Tanuj Yadav Aug 05 '17 at 06:57
-1

Here (a+=3,5,a) gives the output 4 because anything you put after a+=3 does not considered by the value a. for ex: int a=1; a+=2,8,5;

Here value of a=3; since a+=2 is 3.

And after that a+=(a+=3,5,a) evaluates like this.

Here assignment operator always assign right most value to the left operand. so here a is assigned. so this leads to a+=a; therefore the value is 8. since value of a=4; after (a+=3,5,a) operation.

I will give another example int a=2; a+=(a+=2,2,a,10)

will give output as 14. since value of a=4 after (a+=2,2,a,10) operation. and 10 is assigned in right i.e a+=10; this will give us 14.

I hope your question has answered. if you have doubt comment below.

  • @T.Akki This is a wrong answer. This `a += (a += 3, 5, a)` causes undefined behaviour. Read what Jonathan Leffler and Weather Vane has to say. – babon Aug 05 '17 at 10:47