What does “j = 0; j = j++” evaluate to?

by Mark Zhou 15. October 2010 22:41

This is a very simple question, could you give the output of the following code in C#?

static void Main(string[] args)
{
   
int
j = 0;
    j = j++;

   
Console.WriteLine("j = {0}"
, j);
   
Console.ReadKey();
}

Some developers may expect the output result is

j = 1

but however, the output result is shown as following screenshot:

image

So, what’s the trick?

Well, let’s go deep a little bit into the code. The first line is an assignment statement, which assigns an integer 0 to the local variable j. The second line is also an assignment statement but one difference is the right side of the assignment statement (after the equality sign) is an expression. An expression is a statement that can produce a value. j++ is what we called increment, which adds 1 to its original value.

Then let’s see how the C# evaluates this statement j = j++. Because this is an assignment, The value to be assigned to j is the value that the right side expression j++ produces. if the right side expression j++ produces value 1, the output of this program should be “j = 1”, but the actual result shows “j = 0”, which implies that the expression j++ produces a value of 0!

In many books, they say that the expression

j++;

is equivalent to:

j = j + 1;

No doubt, in normal case, it is correct; if we change the code to the following, we will get a different result.

static void Main(string[] args)
{
   
int
j = 0;
    j = (j = j + 1);

   
Console.WriteLine("j = {0}"
, j);
   
Console.ReadKey();
}

image

This time, the result is easy to understand. The expression j = j + 1 simply returns 1, then j = (j = j + 1) is identical to j = 1.

Now you might be confused, why different results? OK, the j++ is special to C, C++, C#, Java and many other languages, it is self-increment but the increment will not be preformed untill the whole expression is executed. In addition, the produced value for the increment expression could be different from its result. see the following code:

int i = 0;
int
n = i++;
Console.WriteLine(n);

The output of this piece of code is: 0. That’s because i++ can lead the value of i add with 1, but this will not happen until the whole expression i++ is executed, so, the produced value of expression i++ is still 0, the line “int n = i++;” is identical to “int n = 0”.

Let’s go more further. See this code:

int i = 0;
int
n = i++ + i++;
Console.WriteLine(n);

This code will result a screen which shows 1. Here is the explanation: when C# is ready to evaluate “int n = i++ + i++;”, it sees the right side of this statement is an expression, so it will evaluate the right side expression from a right to left order. First, the expression “i++” after the “+” sign will be evaluated, as I discussed, the produced value from this expression is 0, now, the expression “i++” before the “+” sign is going to be evaluated, meanwhile, C# knows that the expression “i++” after the “+” sign is evaluated, and as a result of the increment expression, the value of i is now added to 1, therefore i is 1. Again, “i++” produces the value 1 (now i = 1); so expression “i++ + i++” is now identical to “1 + 0”, obviously its produced value is 1. By now, the right side expression is evaluated, which produced a value 1, then, assign this value to n, output it to the command prompt console.

Note if you want to see the value of i after the evaluation, the result output should say i = 2.

At last, let’s go back to the expression “j = j++”, if you can understand the aforementioned explanations, you may be easily to get the truth. First, the “j = j++” is an assignment, the right side expression “j++” is an increment which will produce a value of 0 and later, after the expression is evaluated, the value of j will become 1. Specifically, “j = j++” is identical to the following statements:

// j = j++
// First, right side expression produces value 0.
int
k = j;
// Second, j adds itself to 1.
j = j + 1;
// Then, assign k to j.
j = k;

It is now obvious, the result of this code is j = 0, which is the same result produced by “j = j++”.

To prove this, see the decompiled IL code here. I have added some comments inside the IL to help better understand.

.method private hidebysig static void Main(string[] args) cil managed
{
    .entrypoint
    .maxstack 3
    .locals init (
        [0] int32 j)
    L_0000: nop
    L_0001: ldc.i4.0
    L_0002: stloc.0 // j = 0
    L_0003: ldloc.0 // Load j to the top of the evaluation stack, marked as s[0]
    L_0004: dup // Copy the value of the top of the evaluation stack, and push it to the s[0], now marked as s[1]
    L_0005: ldc.i4.1
    L_0006: add // s[0] = s[0] + 1
    L_0007: stloc.0 // j = 1, 1 is the value of s[0]
    L_0008: stloc.0 // j = 0, 0 is the value of s[1]
    L_0009: ldstr "j = {0}"
    L_000e: ldloc.0
    L_000f: box int32
    L_0014: call void [mscorlib]System.Console::WriteLine(string, object)
    L_0019: nop
    L_001a: call valuetype [mscorlib]System.ConsoleKeyInfo [mscorlib]System.Console::ReadKey()
    L_001f: pop
    L_0020: ret
}

Now what do you think the expression “j = j++ + j++” evaluates to?

Tags: ,

Comments (4) -

Mads
Mads Denmark
6/9/2011 12:03:07 PM #

This is not the same behavior as c++, where the code
#include <iostream>
int main(int argc,char** argv){
  int j=0;
  j=j++;
  std::cout << j << std::endl;
}
will print a 1.

Reply

Wayne Ye
Wayne Ye People's Republic of China
7/28/2011 5:44:20 AM #

Just verified, JavaScript will print 0....

Reply

tom
tom United States
9/15/2011 9:43:13 AM #

this's why we should avoid using ++

Reply

Elizabeth
Elizabeth Romania
2/6/2012 3:46:25 AM #

It's because of how post-fixed incrementation works.
j++ - increment variable and return original value;
++j - increment variable and return updated value.
So when writing j = j++; you increment j, then promptly reassing it its original value.

Reply

Add comment




  Country flag
biuquote
  • Comment
  • Preview
Loading


Translate This Page

About Mark

Mark is a developer who works for building base class libraries and tools for developers.

Mark's Awards

Microsoft Community Contributor

Month List

Who visit this site

Recent Comments

Comment RSS