-3

What is the output of the following program, and why?

#include<stdio.h>
#include<conio.h>
int main()
{
    int a=5;
    a +=a += a += 2;
    printf("%d",a);
    getch();
    return 0;
}
Nick is tired
  • 6,860
  • 20
  • 39
  • 51
  • 2
    undefined behavior i think because there are multiple assignment and reads of the same value in the same line – Tyker May 30 '18 at 10:55
  • 1
    Well, what output do you get *when you run it*? – klutt May 30 '18 at 11:02
  • 2
    Not a duplicate but please read [Why are these constructs (using ++) undefined behavior in C?](https://stackoverflow.com/questions/949433/why-are-these-constructs-using-undefined-behavior-in-c). – Lundin May 30 '18 at 11:22
  • 1
    @klutt: Running a program reveals only one instance of how it may behave. It does not tell you when the behavior is undefined, and it does not tell you how it may behave with other C implementations. It is **not** a proper method for answeting questions such as this. – Eric Postpischil May 30 '18 at 11:30
  • 3
    Everyone: can't close this as "unclear". It is perfectly clear and contains a MCVE. I was trigger-happy myself and closed as dupe to i++ questions but it is not a good dupe so I re-opened it. "I find this newbie FAQ uninteresting" is not a valid close reason. Either find a good duplicate or stay clear of the question. Voting to re-open. – Lundin May 30 '18 at 11:32
  • @SteveSummit: Neither you nor Lundin think it's a good enough question to be upvoted. – Bathsheba May 30 '18 at 11:50
  • @Bathsheba Fixed. – Steve Summit May 30 '18 at 11:51
  • @SteveSummit: Let's leave it up a bit longer then. – Bathsheba May 30 '18 at 11:51
  • @EricPostpischil Nope, but writing what it does when you run it at least shows some effort. – klutt May 30 '18 at 13:07
  • @klutt: Asking people to jump through hoops that are unproductive tasks to satisfy your notions of effort serves no purpose. – Eric Postpischil May 30 '18 at 13:56
  • 2
    @EricPostpischil I disagree. Especially since one of the reasons to vote down is "does not show any research effort" which this question clearly does not. – klutt May 30 '18 at 13:59
  • @EricPostpischil: I hope you don't mind but I've added the output that I get with an old Turbo C compiler I have lying around still. Note that the `#include ` is evidence enough that a Turbo C compiler is used. – Bathsheba May 30 '18 at 14:04
  • 2
    @klutt: Asking somebody to do something productive might be reasonable. Asking somebody to do an **unproductive task** is not. It serves no purpose, wastes time and effort, and misleads people about what methods are useful for finding information. If you had asked not what output they get but rather what documents did they search for information, you might have established a lack of effort. But asking for somebody to do something useless is nothing more than ask them to perform for your entertainment. – Eric Postpischil May 30 '18 at 15:16
  • @klutt In cases like these, asking someone to "just try it" is not just unproductive, it's downright counterproductive. Questioners always want to know what the "right answer" is, and it's very hard to learn that the right answer is that there is no right answer. Trying it just tends to reinforce the notion that what today's compiler happens to emit might be "right". – Steve Summit May 30 '18 at 15:47
  • @SteveSummit Maybe you're right. I'll think of it. – klutt May 31 '18 at 09:57
  • @EricPostpischil See above – klutt May 31 '18 at 09:57

3 Answers3

2

The behaviour of your program is undefined as you are reading from and writing to a in an unsequenced step.


What your ancient compiler is doing is correctly following the C grammar rules and is grouping the expression as

a += (a += (a += 2))

But grouping is not the same as sequencing. From this point the behaviour is undefined. Your compiler appears to evaluate the above to

a += (a += 7)

followed by

a += 14

to yield 28.

Bathsheba
  • 231,907
  • 34
  • 361
  • 483
  • What is now undefined? Can you give an example of another outcome? – Paul Ogilvie May 30 '18 at 11:01
  • @PaulOgilvie: I've clarified that. Another outcome is that the compiler eats my cat. – Bathsheba May 30 '18 at 11:02
  • You mean the compiler could have cached a copy of a, which is not updated in the next step, so another outcome could have been 8? – Paul Ogilvie May 30 '18 at 11:04
  • @PaulOgilvie: Some compilers don't actually increase `a` until the end of the statement. – Bathsheba May 30 '18 at 11:04
  • 1
    The value of `a` is only required to be written once in the whole statement. Since the grouping implies writing a value to it more than once, those writes are unsequenced, and the behaviour is undefined. – Peter May 30 '18 at 11:04
  • Could you add this to your solution so it is more clear why it is not defined? – Paul Ogilvie May 30 '18 at 11:06
  • 2
    This answer would be better if you'd just leave the first paragraph, and remove any attempt to reason with undefined behaviour. In it's current state your answer implies that 28 is predictable outcome, when predictable outcome is impossible. – user694733 May 30 '18 at 11:12
  • 1
    @user694733: I know, rationalising UB is an automatic -1. I feel you can sort of get away with it if you stick to a particular toolchain (here conio.h is the clue). Tell you what, I'll put a line in the answer. – Bathsheba May 30 '18 at 11:17
  • i agree its an undefined behaviors but i tested multiple compilers on godbolt with max optimization and none broke the code – Tyker May 30 '18 at 11:24
  • @Tyker, try one of the earlier MSVC compilers. – Bathsheba May 30 '18 at 11:26
1

This is a tough question without an easy, obvious answer.

The expression is probably undefined, in which case it's meaningless to ask "what could be the possible output?", because it could be anything.

If it's undefined, it's because there are multiple writes (stores) to a without any intervening sequence points. The rightmost a += 2 computes 7 and prepares to store it into a. Next we have the middle a +=, which tries to take the 7 and add it to... what? The old or the new value of a? If it's the old we compute 5+7= 12 and if it's the new we compute 7+7=14, and whichever value we compute, we prepare to store it into a, but does it "win" and overwrite the value that the rightmost a += 2 tried to store, or not? And then the arguments (and the multiplicity of different interpretations and possible answers) proliferate for the leftmost a +=.

Not all assignment expressions are undefined, of course. For example, the old standby

a = a + 1

is well-defined. It both fetches from a and assigns to a, but in this case we don't have to ask, "what if it assigns to a before it fetches from it?", because obviously, it has to fetch from a first, in the process of computing the new value to be assigned. But this argument doesn't rescue a += a += 2, I don't think.

There are newer rules about "sequencing" which do away with the old concept of "sequence points", and the new rules might render this expression well-defined, but I'm not sure.

Unless you're interested in frustrating, head-banging puzzles, it's best to steer clear of expressions like this one. You obviously wouldn't have any use for an expression like this in a real program. It's nearly impossible to figure out (a) if the expression is well-defined and (b) if so, what it's supposed to do, so a program containing an expression like this is unmaintainable; you have to be a hard-core language lawyer to properly understand it.

Naturally it's important to understand how simpler, saner expressions like a += 2 or x += y[i++] work. But for something insane like a += a += a += 2, don't fall into the trap of asking "Wouldn't it help me understand C better if I understand what it means?", because the only thing to understand is that it's borderline, if not absolutely, meaningless.

See also SO's canonical entry on undefined expressions, Why are these constructs (using ++) undefined behavior in C? (although none of the answers there cover this particular case).

Steve Summit
  • 45,437
  • 7
  • 70
  • 103
-6

It depends on the compiler ! But theoretically 28 is the answer ! The assignment will be from right to left so a +=a += a += 2; can be break down as

5+2=7 a+=2
7+7=14 a+=a+=2
14+14=28 a+=a+=a+=2
Bharadwaj
  • 135
  • 1
  • 1
  • 7