How do Prefix (++x) and Postfix (x++) operations work?

GodsCrimeScene picture GodsCrimeScene · Oct 18, 2011 · Viewed 17.7k times · Source

Can someone tell me how prefix / postfix operators really work? I've been looking online a lot but haven't found anything.

From what I can tell prefex first increments, then does the operation and then assigns.
Postfix would do the operation first, then assign and then increment.

But I'm having a bit of trouble with my code:

int x, y;
x = 1;
y = x + x++; // (After operation y = 2)(x=2)

However when I do:

y = x++ + x; // (After operation y = 3)(x=2)

I'm not sure why these operations would be any different. I have two questions:

  • Could you explain the difference?

  • How does this apply to the other operator Prefix?

Answer

Eric Lippert picture Eric Lippert · Oct 18, 2011

This question gets asked a fair amount. Be warned that every time someone asks this question a great many people post incorrect answers. Lots of people have incorrect ideas about how these operators work, including people who write programming books and thereby teach other people falsehoods. Read the other answers here very carefully.

For a correct analysis of the C# behaviour, see:

What is the difference between i++ and ++i?

For C++ any behaviour is correct behaviour, in those cases where you are observing a side effect. C++ does not define when the side effect of the increment is visible. Any two compilers can do it differently.

A good rule to follow is to not rely on the order in which side effects happen in any language, but certainly do not rely on it in C++, because it is not reliable.

To look at your specific case:

int x, y;     
x = 1;     
y = x + x++; 

You report that x and y are both 2. That is correct in C#. In C# the correct behaviour is:

  • evaluate y as a variable
  • evaluate x as a value -- it is 1
  • evaluate x++ as a value. This evaluates x as a variable, then takes its original value which is 1, then increments that value, which is 2, then assigns 2 to x and then results in the original value, which is 1.
  • evaluate 1 + 1, which is 2
  • assign 2 to y.

So x and y are both 2 in C#.

C++ can do the same thing, but it is permitted to evaluate the addition in right-to-left order. That is, it is permitted to do:

  • evaluate x++ as a value. This evaluates x as a variable, then takes its original value which is 1, then increments that value, which is 2, then assigns 2 to x and then results in the original value, which is 1.
  • evaluate x as a value -- it is 2
  • evaluate 1 + 2, which is 3
  • evaluate y as a variable
  • assign 3 to y.

C++ is also permitted to do this:

  • evaluate x++ as a value. This evaluates x as a variable, then takes its original value which is 1, then increments that value, which is 2 ... step missing here ... and then results in the original value, which is 1.
  • evaluate x as a value -- it is 1
  • evaluate 1 + 1, which is 2
  • assigns 2 to x -- the step that was missing before.
  • evaluate y as a variable
  • assign 2 to y.

So in C++, you can get y as 3 or 2, depending on the whim of the compiler writer. In C# you always get that y is 2. In C++, the increment's assignment can happen at any time, as long as it does happen. In C#, the increment's assignment must happen after the incremented value is computed and before the original value is used. (When observed from the executing thread; if you are trying to observe this stuff from another thread or threads, all bets are off.)

In your second example:

y = x++ + x; 

In C# the required behaviour is:

  • evaluate y as a variable
  • evaluate x++ as a value. This evaluates x as a variable, then takes its original value which is 1, then increments that value, which is 2, then assigns 2 to x and then results in the original value, which is 1.
  • evaluate x as a value -- it is 2
  • evaluate 1 + 2, which is 3
  • assign 3 to y.

So the correct answer in C# is that y is 3 and x is 2.

Again, C++ can do these steps in any order. C++ is permitted to do:

  • evaluate x as a value -- it is 1
  • evaluate x++ as a value. This evaluates x as a variable, then takes its original value which is 1, then increments that value, which is 2, then assigns 2 to x and then results in the original value, which is 1.
  • evaluate 1 + 1, which is 2
  • evaluate y as a variable
  • assign 2 to y.

Again, in C++ the correct answer is that y is 2 or 3, depending on the whim of the compiler writer. In C# the correct answer is that y is 3.