2

Taking an intro c++ class, and the professor today was talking about loops, increments, and decrements. so we were examining how many times a simple do-while loop would run, and I noticed that during the output of the following code, the int y is displayed first as a 2, however the postfix-notation for increments is used first and, according to my professor, is also given precedence(like in the x variable displayed). so why is y not first displayed as: "1 3" in the output window?

probably a very simple answer, but he did not know immediately, and asked us to see if we can find out. we were using dev c++'s newest version.

#include <iostream>
using namespace std;

int main()
{
    int x=1;
    int y=1;

    do
    {
        cout << "x: " << " " << ++x << " " << x++ << endl;
        cout << "y: " << " " << y++ << " " << ++y << endl;
    }while(x<=10);

    return 0;
}

if you run it, the display will look like this:

x:  3 1
y:  2 3
x:  5 3
y:  4 5
x:  7 5
y:  6 7
x:  9 7
y:  8 9
x:  11 9
y:  10 11

with my limited understanding i came up with this: since there are multiple increment operations used in the same statement, they are both performed before the cout statement displays the information to the console.
but looking for maybe a more precise answer/explanation

exexzian
  • 7,782
  • 6
  • 41
  • 52
  • 2
    http://stackoverflow.com/questions/5433852/when-does-postincrement-i-get-executed – jogojapan Mar 01 '13 at 02:58
  • 3
    it seems to be a undefined (or implementation-dependent) behavior for C++, with multiple assignment to the same variable in same statement. – Adrian Shum Mar 01 '13 at 03:01
  • so is the answer just "undefined behavior" within the compiler? – user2121985 Mar 01 '13 at 03:08
  • @user2121985: It's actually "behavior undefined by the C++ spec", so each compiler can implement it however they feel like. I once got bit by a bug writing code like this which gave one result in one version of a C++ compiler, and a different result in the next version of the same compiler. – Bob Murphy Mar 01 '13 at 03:17
  • This resolves to chained function calls: `cout.operator<<("x: ").operator<<(" ").operator<<(++x).operator<<(" ").operator<<(x++).operator<<(endl);` I knew the order arguments are executed is undefined, but this is slightly different. Incidentally *why* is any of it undefined? It seems perfectly easy for them to have just defined it to be the way *everyone* intuitively thinks it should work. – David Mar 01 '13 at 03:20
  • 1
    @Dave: the issue is that the standard specifies: `Except where noted, evaluations of operands of individual operators and of subexpressions of individual expressions are unsequenced`. Unlike a function call, the << and >> operator does not create a sequence point. – Lie Ryan Mar 01 '13 at 03:41
  • 1
    @Dave: however the << and >> here is an overloaded operator, and overloaded operator does introduce sequence point like function calls. I'm not actually quite sure whether this should be an undefined behaviour. – Lie Ryan Mar 01 '13 at 03:51
  • 1
    @LieRyan Why do you think overloaded operators introduce extra sequencing? – jogojapan Mar 01 '13 at 03:51
  • 1
    @jogojapan: I don't have the standard at hand, but http://www.viva64.com/en/t/0065/, http://msdn.microsoft.com/en-us/library/d45c7a5d(v=vs.90).aspx, http://en.m.wikipedia.org/wiki/Sequence_point, and http://stackoverflow.com/questions/4638364/undefined-behavior-and-sequence-points-reloaded seems to imply so. – Lie Ryan Mar 01 '13 at 03:59
  • @LieRyan Yes, you are right: The last sentence of 1.9/15 says it. What shocks me is that this means the evaluation order of `a + b` for user-defined types `a` and `b` depends on whether `operator+` is a member function or a free function. – jogojapan Mar 01 '13 at 04:09
  • 1
    @LieRyan But the order of the evaluation is still undefined: In `cout.operator(a).operator(b)`, the order of the two operator calls is determined, but the evaluation of the arguments `a` and `b` doesn't have to be in any particular order. The same is true of `operator(operator(cout,a),b)`. And that of course means, the effect of the expression given by the OP is undefined behaviour. – jogojapan Mar 01 '13 at 07:49
  • @jogojapan: Yes, I think you're right, while there's a sequence point in the call, the order is still undefined. – Lie Ryan Mar 01 '13 at 08:04

1 Answers1

1

++y increments and assigns the new value of y before a reference of int y is passed to operator<<(std::ostream&, const int&) and y++ increments and assigns y after operator<<(std::ostream&,const int&) returns

So, you land up printing 2 the first time because y=1 is passed in to opertator<< y++ is called to print 2, and after the call to operator<< y is assigned 2.

The second call to operator<< on y has y set to 2, ++y is called before the reference is passed to operator<< and y is 3.

Joel
  • 2,928
  • 2
  • 24
  • 34