0

Why this snippet:

int i = 0;
cout << ++i << " " << ++i;

produces 2 2 instead of 1 2?

EDIT: Pointers to answers about undefined evaluation order don't clear this issue for me. If cout << ++i << " " << ++iis translated to f (++i, " ", ++i) there seem to be only 2 relevant cases:

  1. 1st parameter is evaluated before 3rd one: f (0, " ", 1)
  2. 3rd parameter is evaluated before 1st one: f (1, " ", 0)

Where is 2 2 coming from?

EDIT: OK, I get it: "Between the previous and next sequence point an object shall have its stored value modified at most once by the evaluation of an expression".

Paul Jurczak
  • 7,008
  • 3
  • 47
  • 72
  • The ordering of the overloaded `<<` is poorly defined, because it becomes 2 parameters to a function. Don't rely on a particular order for it. – Dave Apr 14 '13 at 20:03
  • Which Compiler and OS? – bash.d Apr 14 '13 at 20:04
  • 1
    And over and over and over and over... –  Apr 14 '13 at 20:04
  • @H2CO3 Isn't it time for SO to add an automated duplicate detection for the most common cases? ;) – Daniel Frey Apr 14 '13 at 20:06
  • [This answer from the duplicate question](http://stackoverflow.com/a/4177063/16287) will likely explain your predicament better than the accepted one. – Drew Dormann Apr 14 '13 at 20:08
  • @DanielFrey I am filing a feature request on Meta! (I am going to lose all of my 229 Meta reputation >.< ) –  Apr 14 '13 at 20:34

1 Answers1

1

Because this is Undefined Behaviour
Also it cannot output 0(well strictly saying in case of UB result can be anything, including 0 as output, but that is really unlikely) because you use pre increment, that will result in i being incremented prior to being passed to operator<<

there seem to be only 2 relevant cases:

1st parameter is evaluated before 3rd one: f (0, " ", 1)
3rd parameter is evaluated before 1st one: f (1, " ", 0)

First, there is no relevant cases in case of UB, you can get 0,1,2,5, 0xABCD, AV, whatever.
Second you use pre increment, thus value will be incremented before being passed to function.
Third f(++i, " ", ++i); apart from UB, that was already mentioned, will evaluate both preincrements prior to call, increasing i value to 2.

Community
  • 1
  • 1
alexrider
  • 4,449
  • 1
  • 17
  • 27
  • I think you may be too pessimistic here. What's is undefined is evaluation order, but not the validity of evaluation itself, that is the results will belong to {0, 1, 2}. Getting 5 is not allowed. This quote from C++ standard describes it: "Between the previous and next sequence point an object shall have its stored value modified at most once by the evaluation of an expression." – Paul Jurczak Apr 14 '13 at 20:51
  • Here is another quote $1.9/15- "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." so this is UB. Thru yes for most real compiler implementations you will get something like 0,1,2 with 0 being unlikely. Also you have your object modified twice, thus can't relay on that quote. – alexrider Apr 14 '13 at 21:00