tags:

views:

171

answers:

4

I have a variable declared like this:

int j=0;

When I write:

cout<<j++<<" "<<j++<<" "<<j++<<"\n";

I receive this output:

2 1 0

I expect to receive this output:

0 1 2

Could you explain the result?

A: 

this is confusing but normal because order of evaluation for this operator is right to left.

oykuo
Have U tried the above thing. If not try it..
I tried it and I know the result should be 2 1 0 because as I explained the order of evaluate is right to left.
oykuo
+9  A: 

The spec says that if you modify the same variable more than once within the same sequence point, the result is "undefined".

Sequence points are between ; (and also , is a sequence point, not sure if there are others).

What you're trying is the same as the better known trivia question, "what's the value of x after the second assignment?"

int x;
x = 0;
x = x++;

The answer is "undefined".

Binary Worrier
In the users code, there is a sequence point at each use of the << operator, because these are really function calls.
anon
I believe the answer is correct, but the reason is somewhat subtle. My understanding is that all the increments can happen before any of the function sequence points, but I'm going to ask exactly that question separately and we can fight it out there :-)
James Hopkin
@Neil. That's not totally accurate. The only restriction on function calls is that all parameters must be fully evaluated before the function is called. With chained functions like this it is a single expression and all calls are all between the same sequence points.
Martin York
+3  A: 

This is because your compiler is likely evaluating the equation from right to left.

check out this question for more info.

Edit: Tested on g++ 4.4.0

#include <iostream>

int main (int argc, char **argv) {
int j = 0;
std::cout << j++ << " " << j++ << " " << j++;
return 0;
}
[john@awesome]g++ rtl.cpp -o rtl
[john@awesome]./rtl
0 1 2
[john@awesome]
John T
cool, I didn't know this is compiler dependent. I've always thought this is just how << operator works. +1
oykuo
I just tested your code on g++ 4.4.0 and got 2 1 0. This is taking undefined behaviour too far :-)
anon
you're kidding, right?
John T
No, I'm not - my version string: g++.exe (TDM-1 mingw32) 4.4.0
anon
Why are you surprised that the order changes. The compiler provides no grantees about the order. I suspect the ordering is more to-do with the underlying ABI being used rather than the compiler version.
Martin York
The other thread I've linked to points towards a platform issue, not undefined behavior. It's just not something you can count on if you're writing platform independent code I suppose. This was an interesting little experiment, I love these threads.
John T
I wasn't really suprised, hence the smiley...
anon
I just copied the above code but i am getting 2 1 0
what compiler and OS are you on though
John T
g++ 4.0.0 linux fd-4
I am getting 2 1 0 on g++ 4.3 on Linux.
Zifre
+5  A: 

This code is equivalent to

... operator<<( operator<<( operator<<( operator<<(cout,j++), " " ), j++ ), "\n" ); ...

Though order of function call is given, order of parameters evaluation is not. So there is no guarantees which j++ is evaluated first. There are modifications of j without sequence points between them, so you see result of Undefined Behaviour.

[Edit1] There is inaccuracy in previous. operator<<(int) is a member function of basic_ostream. Denote operator<<(int) as f, operator<<(ostream&,const char*) as g. Then we have

...g(f(j++)," ").f(j++)...

Order of evaluation still can be: eval(j++) -> eval(j++) -> sequence point -> call(f) -> sequence point -> call(g) -> sequence point -> call(f). This is because of following quote from standard [expr.4]:

Except where noted, the order of evaluation of operands of individual operators and subexpressions of individual expressions, and the order in which side effects take place, is unspecified

Konstantin
That would be true if operator<< were always implemented as a non-member function. For some compilers it is a member of basic_ostream.
anon