3

Possible Duplicate:
Could anyone explain these undefined behaviors (i = i++ + ++i , i = i++, etc…)

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?

Community
  • 1
  • 1

4 Answers4

10

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
  • 50,774
  • 20
  • 136
  • 184
  • In the users code, there is a sequence point at each use of the << operator, because these are really function calls. –  May 07 '09 at 09:59
  • 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 May 07 '09 at 10:17
  • 3
    @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 May 07 '09 at 10:18
6

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 Tenzin
  • 12,398
  • 3
  • 22
  • 20
  • 1
    That would be true if operator<< were always implemented as a non-member function. For some compilers it is a member of basic_ostream. –  May 07 '09 at 10:01
3

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]
Community
  • 1
  • 1
John T
  • 23,735
  • 11
  • 56
  • 82
  • cool, I didn't know this is compiler dependent. I've always thought this is just how << operator works. +1 – oscarkuo May 07 '09 at 09:55
  • I just tested your code on g++ 4.4.0 and got 2 1 0. This is taking undefined behaviour too far :-) –  May 07 '09 at 10:06
  • No, I'm not - my version string: g++.exe (TDM-1 mingw32) 4.4.0 –  May 07 '09 at 10:11
  • 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 May 07 '09 at 10:22
  • 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 May 07 '09 at 10:29
  • I wasn't really suprised, hence the smiley... –  May 07 '09 at 10:30
  • I just copied the above code but i am getting 2 1 0 –  May 07 '09 at 10:34
  • what compiler and OS are you on though – John T May 07 '09 at 10:39
  • I am getting 2 1 0 on g++ 4.3 on Linux. – Zifre May 07 '09 at 11:45
-1

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

oscarkuo
  • 10,431
  • 6
  • 49
  • 62