0

Why doesn't the code (2) below produce the same output as the code (1)? Let's say you entered "4" as input:

(1)

    int x;
    cout << "enter integer: ";
    cin >> x;
    cout << x++;
    cout << ++x;
    cout << x;

The output of the above is "466" (as expected).

(2)

    int x;
    cout << "enter integer: ";
    cin >> x;
    cout << x++ << ++x << x;

The output of the above is "554". Why??

7
Contributors
17
Replies
103
Views
1 Month
Discussion Span
Last Post by sgw
Featured Replies
  • No reply from a C++ buff yet? At the risk of making a fool of myself I'll try. I'm no C++ expert, but this looks to me like another example of C++'s "undefined" behaviours - specifically the order in which things of the same priority are done within some expressions … Read More

  • That's one of those questions they like to put on the exam to see if you know the inner workings of c/c++ even though no sane c/c++ programmer would ever code like that. Read More

  • Another analogy. Remember Black Hawk Down? The part when the Ranger Captain berates the Delta Force operator for having a "hot" weapon (i.e. the safety not engaged) and the Delta Force operator mimes his finger pulling the trigger and says "This is my safety"? That guy probably became a C++ … Read More

  • That's more or less my understanding too - order of execution was left undefined/unspecified in places where the experts thought it would allow compiler writers more scope for optimisation. Nowdays we know that (with a very few exceptions) the last 1% of code efficiency is not a problem, but software … Read More

  • > But why doesn't that happen with, say, the following? It DOES happen... cout << "A" << "B" << "C"; Parsing right to left ("C" then "B" then "A") 1. Push "C" onto stack. 2. Push "B" onto stack. 3. Push "A" onto stack. 4. Call cout function with this … Read More

0

Yes all good - unseparated output. Add new lines after each output.

cin >> x;
cout << x++ << "\n";
cout << ++x << "\n";
cout << x << "\n";

Edited by AndrisP

0

No the problem is not new line or not. The problem is why the two codes produce different output. Similarly, the following two also produce different output:

(3)

    int x;
    cout << "enter integer: ";
    cin >> x;
    cout << x++ << endl;
    cout << ++x << endl;
    cout << x;

Output is 4 6 6 (on different lines). Where as:

(4)

    int x;
    cout << "enter integer: ";
    cin >> x;
    cout << x++ << endl << ++x << endl << x;

This has the output 5 5 4 (on differenet lines).

In theory, cout << x++ should display the current value, then increase x; and cout << ++x should first increase x, then display the new value. But in (2) and (4) this doesn't seem to be the case. Could anyone explain? Thanks.

0

Another example, why the following code output is "55" instead of "45"?
(5)

    int x;
    cout << "enter integer: ";
    cin >> x;
    cout << x << ++x;
2

No reply from a C++ buff yet? At the risk of making a fool of myself I'll try.
I'm no C++ expert, but this looks to me like another example of C++'s "undefined" behaviours - specifically the order in which things of the same priority are done within some expressions is not defined (the order is only defined at specific checkpoints (I forget what the C++ term is), but not inbetween). There's a much-discussed variant of your problem in which various x++, ++x and x values are used as parameters in a function call which suffers from the same problem.

Votes + Comments
Actually, they are well-defined behaviors for both C and C++
1

That's one of those questions they like to put on the exam to see if you know the inner workings of c/c++ even though no sane c/c++ programmer would ever code like that.

0

Thank you so much, JamesCherrill. That makes sense. Thanks for the reference. Guess one should avoid writing such statements (as Reverend Jim says, not 'sane').

(I wonder why when I wrote similar statements a year or so ago using different computers I didn't get the surprising output. Maybe it's erratic depending on which computer used...)

1

There's a much-discussed variant of your problem in which various x++, ++x and x values are used as parameters in a function call which suffers from the same problem.

I know it's hard, but try to understand that this is a feature, not a bug. They didn't miss this aspect. Smart people studied it, pondered it, and decided that it was best to make stuff like this undefined. Trying to understand WHY they chose this route helps you understand what C++ is designed for and when it should be used where and when it SHOULDN'T be used.

If C++ was an electrician, it would design a house with no fuses or breakers, use the smallest possible diameter wire for the rated amperage, and give the people living there the schematic. If the people living there protested that running the hot tub and the washing machine at the same time would burn down the house, the electrician would tell them not to run both at the same time.

1

Smart people ... decided that it was best to make stuff like this undefined

Yes, I did understand that. My opinion was formed including that knowledge. I'm more worried about the people who moved into that house, turned some stuff on, and lost everything in house fire that should never have happened. :)

0

Good analogy--helpful!

Edited by sgw

3

Another analogy. Remember Black Hawk Down? The part when the Ranger Captain berates the Delta Force operator for having a "hot" weapon (i.e. the safety not engaged) and the Delta Force operator mimes his finger pulling the trigger and says "This is my safety"? That guy probably became a C++ programmer after he retired from the military. :)

Re-reading my last post, the wording came off a little different than intended. Hopefullly not preachy or lecturing.

Now to the actual original question. Note that I am not a compiler writer or very knowledgable with the C++ Standard. That said, and oversimplifying, I'm guessing that when a cout line with several << operators in it gets parsed, a stack is formed with with the << delimiting the stack items. Since a stack is First In Last Out, items are placed onto the stack RIGHT TO LEFT since they have to be displayed LEFT TO RIGHT.

cout << x++ << ++x << x;

There are three items that need to go onto the stack, and they must go onto the stack in the following order...

  1. x (4)
  2. ++x (increment x to 5, THEN place 5 on stack)
  3. x++ (place 5 on stack, THEN increment x to 6)

Thus the process is as follows...

  1. Push 4 onto stack
  2. Increment x. x = 5
  3. Push 5 onto stack.
  4. Push 5 onto stack.
  5. Increment x. x = 6.
  6. Call cout subroutine with a stack of 5,5,4 to display
  7. Pop 5 off stack.
  8. Output the 5 that you popped.
  9. Pop 5 off stack.
  10. Output the 5 that you popped.
  11. Pop 4 off the stack.
  12. Output the 4 that you popped.

Output is "554", as you saw.

I haven't actually compiled this and checked, and like I said, oversimplified, but if I am the compiler writer, making multiple increments in the same statement undefined allows me to implement the cout statement as a stack quickly and efficiently WITHOUT keeping track of x. Imagine how much easier this is for me to write as the compiler writer if I am allowed to push hard-coded values onto the stack rather than variables that I have to keep track of left to right. Think how much more efficient I can make that code if I do not need to keep track of this.

Votes + Comments
A few heads nod, others, all hair pulled out.
2

That's more or less my understanding too - order of execution was left undefined/unspecified in places where the experts thought it would allow compiler writers more scope for optimisation. Nowdays we know that (with a very few exceptions) the last 1% of code efficiency is not a problem, but software maintenance and porting are massive issues.

0

It's a question of when the increment occurs. Depending on the other code, the increment will either occur before the other statements are executed or after they are executed.

Edited by zimmatore_1

0

There are two kinds of increments for integers - pre-fix and post-fix. X++ is one and ++X is the other. You figure it out! Or read your C/C++ programming manual!

0

Another analogy. Remember Black Hawk Down?

First time heard of the movie ;-)

There are three items that need to go onto the stack, and they must go onto the stack in the following order...
x (4)
++x (increment x to 5, THEN place 5 on stack)
x++ (place 5 on stack, THEN increment x to 6)

Thus the process is as follows...

Push 4 onto stack
Increment x. x = 5
Push 5 onto stack.
Push 5 onto stack.
Increment x. x = 6.
Call cout subroutine with a stack of 5,5,4 to display
Pop 5 off stack.
Output the 5 that you popped.
Pop 5 off stack.
Output the 5 that you popped.
Pop 4 off the stack.
Output the 4 that you popped.

But why doesn't that happen with, say, the following?

cout << "A" << "B" << "C";

The output will be ABC, not CBA. ?

3

But why doesn't that happen with, say, the following?

It DOES happen...

cout << "A" << "B" << "C";

Parsing right to left ("C" then "B" then "A")

  1. Push "C" onto stack.
  2. Push "B" onto stack.
  3. Push "A" onto stack.
  4. Call cout function with this stack...
  5. Pop "A" from stack.
  6. Display "A"
  7. Pop "B" from stack.
  8. Display "B"
  9. Pop "C" from stack.
  10. Display "C"

End result is "ABC" is displayed to the screen.

0

Ah, I see now. Just re-read your previous post more carefully , it's the right-most x that got processed first, so it got the earlier value of 4, but it was output the last, but it's still 4. In the ABC example there is no such problem, C remains C.

I tested some other cout statements with various orders of ++x, x++, --x, x-- and x, and using your explanation the output predictions turned out all correct!

Thanks for helping understand!

Edited by sgw

Have something to contribute to this discussion? Please be thoughtful, detailed and courteous, and be sure to adhere to our posting rules.