3

Possible Duplicate:
Unexpected order of evaluation (compiler bug?)

I couldn't predict the output for this program :

#include<iostream>
using namespace std;

int *p(int *a)
{
    (*a)++;
    return a;
}
int main()
{
    int i=0;

    cout<<i++<<" "<<(*p(&i))++<<" "<<i++<<" "<<i<<endl;
    return 0;
}

When compiled in vs2008, it outputs 3 2 0 4. Can anybody explain why it's not 0 2 3 4 ?

Note: It works great if there is no function call to p.

Thanks in advance!

Community
  • 1
  • 1
Khaledvic
  • 534
  • 4
  • 16
  • 5
    Yes, the behaviour is undefined. The question you should be asking yourself is why you would want to write such code. The answer is that you don't. – David Heffernan Jan 02 '12 at 19:16

2 Answers2

3

Undefined behaviour. Could do anything.

See this answer for a good explanation.

Community
  • 1
  • 1
Oliver Charlesworth
  • 267,707
  • 33
  • 569
  • 680
  • 3
    So `cout << x << y` could print y and then x?! – atoMerz Jan 02 '12 at 19:17
  • isn't it something depends on priority ! and why it works ok when I don't call "p" ? – Khaledvic Jan 02 '12 at 19:17
  • 2
    AtoMerZ: no, because that is not undefined. @Khaledvic: "Could do anything" means it can also "work" (or appear to). – R. Martinho Fernandes Jan 02 '12 at 19:18
  • @Khaledvic the order in which each thing between each `<<` is undefined, but the order in which the `operator<<` calls occur, after everything between each `<<` are all evaluated, is left to right. – Seth Carnegie Jan 02 '12 at 19:27
  • What's the scenario behind the 3 2 0 4 output? I found no logical order in which compiler evaluates the four operands, first the 3rd one, then 2nd, then 1st and last the 4th operand! Is it some kind of lazy evaluating? – Hossein Jan 02 '12 at 19:31
  • It's still unclear to me (even when I read the answer in link). What makes his case undefined and mine not undefined. if I had said `cout << x << y << z` could it print z x y? – atoMerz Jan 02 '12 at 19:34
  • 1
    @AtoMerZ: Because your case isn't modifying any of the operands. – Oliver Charlesworth Jan 02 '12 at 19:34
  • That's right. But in `cout << x << y << z` couldn't z be evaluated before x and y? What if I had said `cout << x++ << y++ << z++`? – atoMerz Jan 02 '12 at 19:36
  • @AtoMerZ: Ok, to be more specific; your case is not operating on the same variable multiple times with side effects. (Of course, if `y` and `z` are references to `x`, then your new example **will** be undefined.) – Oliver Charlesworth Jan 02 '12 at 19:38
0

The point isn't cout's precedence, but the ++ operator.
This operator's side effect can take place any time between two sequence points, which means anywhere in the statemenet, in this case. The exact order it happens is, as @oli-charlesworth says, undefined.
cout's precedence is left to right, so the leftmost is printed first. But the value of each number depends on the behavior of ++.

ugoren
  • 16,023
  • 3
  • 35
  • 65
  • "cout's precedence is left to right" - this doesn't make any sense. `cout` is an object, not an operator. Also, sequence points are not really the problem here; the problem is that the sequence of evaluation of arguments to `operator<<` is unspecified. – Oliver Charlesworth Jan 02 '12 at 19:58
  • Indeed, the << operator's precedence is left to right, not cout. And I do think sequence points matter here (just as it does in "i++ + i++"), though maybe order of evaluation is more basic. But my main point was that it isn't (as someone mistakenly understood from your answer) order of precedence. – ugoren Jan 02 '12 at 21:30