Behavior of post increment in cout [duplicate]

#include <iostream>
using namespace std;

main(){

int i = 5;

cout << i++ << i--<< ++i << --i << i << endl;


}

The above program compiled with g++ gives output :

45555

While the following program:

int x=20,y=35;

x =y++ + y + x++ + y++;

cout << x<< endl << y;

gives result as

126

37

Can anyone please explain the output.


Solution 1:

cout << i++ << i--

is semantically equivalent to

operator<<(operator<<(cout, i++),   i--);
           <------arg1--------->, <-arg2->

$1.9/15- "When calling a function (whether or not the function is inline), every value computation and side effect associated with any argument expression, or with the postfix expression designating the called function, is sequenced before execution of every expression or statement in the body of the called function. [ Note: Value computations and side effects associated with different argument expressions are unsequenced. —end note ]

C++0x:

This means that the evaluation of the arguments arg1/arg2 are unsequenced (neither of them is sequenced before the other).

The same section in the draft Standard also states,

If a side effect on a scalar object is unsequenced relative to either another side effect on the same scalar object or a value computation using the value of the same scalar object, the behavior is undefined.

Now there is a sequence point at the semicolon at the end of the full expression below

operator<<(operator<<(cout, i++), i--);
                                      ^ the interesting sequence point is right here

As is clear, evaluation of both arg1 and arg2 lead to side effect on the scalar variable 'i', and as we saw above, the side effects are unsequenced.

Therefore the code has undefined behavior. So what does that mean?

Here is how 'undefined behavior' is defined :) in the Standard.

Permissible undefined behavior ranges from ignoring the situation completely with unpredictable results, to behaving during translation or program execution in a documented manner characteristic of the environment (with or without the issuance of a diagnostic message), to terminating a translation or execution (with the issuance of a diagnostic message). Many erroneous program constructs do not engender undefined behavior; they are required to be diagnosed.

Do you see correlation with @DarkDust's response 'The compiler is even allowed to set your computer on fire :-)'

So any output you get from such a code is really in the dreaded realm of undefined behavior.

Don't do it.

Only thing that is defined about such code is that it helps OP and many of us get lots of votes (if answered correctly) :)

Solution 2:

The result of the second program's expression is undefined. The compiler is even allowed to set your computer on fire :-) You're not allowed to modify a variable twice within one sequence point (in this case: from = to ;).

Edit:

For detailed explanations, see the C FAQ, specifically question 3.2.

Solution 3:

Adding to other's answers:

If you are using g++, using the -Wsequence-point option tells that:

$ g++ -Wsequence-point a.cpp
a.cpp: In function ‘int main()’:
a.cpp:8: warning: operation on ‘i’ may be undefined
                                          ^^^^^^^^^

Solution 4:

Undefined behaviour, so anything could happen