x+=x++;


Today I was looking through an internal C# user group list. One of the messages was about “x+=x++;” and what should be the right behavior. I thought this is more generally interesting, so I decided to blog it. But first, DO NOT WRITE THAT CODE!!!

Ok, with that out of the way, we can start…

Let’s take this code as an example:

int x = 3;

x += x++;

The first thing the compiler does whenever it sees something like z += y is to convert it to z = z + y. This is obviously true for +=, -=, *=, and /=. Ok, this was easy. Now we have just to consider:

x= x + x++;

This, by the way, gives the same result as:

x = x + x;

This, by the way, gives a different result from:

x = x++ + x;

This, by the way gives the same result as:

x = x + ++x;

As maddening as this may seem, it actually makes sense (once you understand how it works). But first, what is the difference between x++ and ++x? x++ returns the value of x to the current expression and then increments x. ++x increments x and then return its value to the current expression. Given this factoid (and knowing that c# evaluates expressions left to right), we can then consider what happens in the following case:

int x = 3;

x = x + x++;

Here is how the compiler conceptually evaluates it:

  1. x = (x) + x++ -> the first x gets evaluated and returns 3, x = 3
  2. x = 3 + (x)++ -> x gets evaluated and returns 3, x = 3
  3. x = 3 + (x++) -> x++ gets evaluated and x is incremented (to 4), x = 4
  4. x = (3 + 3) -> 3 + 3 gets evaluated and returns 6, x = 4
  5. (x = 6) -> x is assigned to 6 (overriding the previous value of 4)

Now let’s see how this one works:

int x = 3;

x = x++ + x;

  1. x = (x)++ + x -> x gets evaluated and returns 3, x =3
  2. x = (x++) + x -> x++ gets evaluated and x is incremented, x=4
  3. x = 3 + (x) -> x gets evaluated and returns 4, x = 4
  4. x = 3 + 4 -> 3+4 gets evaluated and returns 7, x = 4
  5. (x=7) -> x is assigned to 7 (overriding the previous value of 4)

Now let’s get to this one:

int x = 3;

x = x + ++x;

  1. x = (x) + ++x -> x gets evaluated and returns 3, x=3
  2. x = 3 + (++x) -> ++x gets evaluated and x is incremented, x=4
  3. x = 3 + (x) -> x gets evaluated and returns 4, x=4
  4. x = 3 + 4 -> 3+4 gets evaluated and returns 7, x = 4
  5. (x=7) -> x is assigned to 7 (overriding the previous value of 4)

I hope this is clear. By the way, in c++ the behavior for this expression is undefined…

But now… why did we make this legal? Why not err or warn at compilation time? Well…

  • We were wrong, we should have erred or warned, but now it is too late because if we change this we break code OR
  • It is quite complex to form a set of guidelines that the compiler can evaluate to be able to err just in the bizarre cases OR
  • We prefer to spend our time working on things people really care about instead of these corner-corner-corner cases

Does it matter which of the previous options is the correct one? Not really because…

YOU ARE NOT GOING TO WRITE THAT CODE J

Comments (17)

  1. What happens if you code something like this: x+=x++; Take a look at this great article….

  2. <a href="http://weblogs.asp.net/lucabol/">Luca Bolognese</a> writes in his blog:<br>

    <br>

    <div style="margin-left: 40px;">Today I was looking through an internal C# user group

    list. One of the messages was about <code>x+=x++;</code> and what should be the

    right behavior. I thought this is more generally interesting, so I

    decided to blog it. <br>

    <br>

    But first, DO NOT WRITE THAT …

  3. And why VB doesn’t have them.

  4. Anonymous says:

    pbblog &raquo; Fun with Compiler Minutia