Ordering

By | 2013-07-11

Consider this:

#include <iostream>
using namespace std;

int x = 10;

int f(int& x)
{
    x++;
    return x;
}
void g(int& x)
{
    x *= 2;
    return x;
}

int h(int f, int g)
{
    return f + g;
}

int main()
{
    clog << "h() = " << h(f(x), g(x)) << endl;

    return 0;
}

What would you say is the output?

You might be surprised to learn that the answer is undefined.

The call to h() is not required to evaluate its parameters in any particular order. Therefore x could be incremented first, or doubled first.

  • f() then g() means h(11, 22)
  • g() then f() means h(21, 20)

Ouch.

The reason this happens is because we’ve violated a rule that goes right back to C. You must not modify the same variable more than once between sequence points. It’s easy to forget that the arguments to a function are all within the same sequence point – hence the comma between the parameters rather than a semi-colon.

I mention it only because I read this complaint:

In a sensible world, left-to-right evaluation would be specified by the standards.

Unfortunately not. There is no reason that any particular ordering is “correct”, and C/C++ has always been upfront about multiple access between two sequence points.

Leave a Reply