0

Possible Duplicate:
Order of evaluation of arguments using std::cout

#include<iostream>
#include<cstdio>
#include<cstring>

using namespace std;

static int series_num;

void setint(int num) {
    series_num = num;
}

int ser() {
    series_num = series_num + 23;
    return series_num;
}

int main() {
    setint(50);
    cout << ser() << " " << ser();
    getchar();
    getchar();
    return 0;
}

returns me 96 73

#include<iostream>
#include<cstdio>
#include<cstring>

using namespace std;

static int series_num;

void setint(int num) {
    series_num = num;
}

int ser() {
    series_num = series_num + 23;
    return series_num;
}

int main() {
    setint(50);
    cout << ser();
    cout << ser() << endl;
    getchar();
    getchar();
    return 0;
}

returns me 73 and 96

Community
  • 1
  • 1
AnkitSablok
  • 3,021
  • 7
  • 35
  • 52
  • 2
    Also lookup [“sequence point”](http://stackoverflow.com/questions/4176328/undefined-behavior-and-sequence-points) here on stackoverflow. – Benoit Feb 21 '12 at 12:27
  • 1
    Identical to: http://stackoverflow.com/questions/7718508/order-of-evaluation-of-arguments-using-stdcout – ArjunShankar Feb 21 '12 at 12:33

3 Answers3

3
 cout << ser() << " " << ser();

Here you have two calls to ser() without any sequence point between them.
Thus, it is unspecified what will be evaluated first.

On the contrary, in your second example, the behaviour is well-defined and predictable.

Benoit
  • 76,634
  • 23
  • 210
  • 236
  • 1
    There are sequence points at each function call and return, so there is no undefined behavior. It is still unspecified which of the two calls to `ser` occur first, since there are no sequence points between the calls, and neither depends on the results of the other. – James Kanze Feb 21 '12 at 12:44
1

In the first case you use one sequence making two calls to ser(), the calls are made from right to left so you have 96 73.

Eregrith
  • 4,263
  • 18
  • 39
0

In the first case

cout << ser() << " " << ser();

Is equivalent to:

operator<<(cout.operator<<(ser()),"").operator<<(ser());

Is a full expression. The evaluations of operands of individual operators and of subexpressions of individual expressions are unsequenced. Thus it is undefined the order in which both calls to ser() are performed.

The only thing you know is:

  1. First call to ser() is performed before its insertion to cout.
  2. Second call to ser() is performed before its insertion to cout.
  3. It is undefined which call to ser() is performed before (they are unsequenced).

Thus it is valid that an implementation returns 96 73 and a different implementation returns 73 96.

Furthermore, In an expression that is evaluated more than once during the execution of a program, unsequenced and indeterminately sequenced evaluations of its subexpressions need not be performed consistently in different evaluations. This allows that if the expression

cout << ser() << " " << ser();

is run twice within a program different orders are selected.

In the second program.

cout << ser();
cout << ser() << endl;

Are two full expressions (in two separate statements). In that case, the first statement is sequenced before the second statement, because every value computation and side effect associated with a full-expression is sequenced before every value computation and side effect associated with the next full-expression to be evaluated.

As a result the only possible outcome is 73 96.