Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unexpected post-increment behavior in assignment

Tags:

c#

expression

Could you please help me understand why variable a is not incremented in the first case but it is in the second case?

Case 1:

int a = 10;            
a = a++;
Console.WriteLine(a); //prints 10

Case 2:

int a = 10;                        
int c = a++;
Console.WriteLine(a); //prints 11

I've gone through other similar questions but couldn't find any specifics.

UPDATE 1: How I think the program flows

Case 1:

1. 'a' is assigned 10
2. 'a' is assigned 10 before increment happens
3. 'a' is incremented by 1 (Why doesn't this step affect the final value of 'a'?)
4. 'a' is printed --> 10

Case 2:

1. 'a' is assigned 10
2. 'c' is assigned 10 before 'a' is incremented
3. 'a' is incremented by 1 (Why does the increment of 'a' work here?)
4. 'a' is printed --> 11

UPDATE 2: Thanks to all the answers, i think i've understood it, please correct me if i'm wrong.

Case 1:

1. `a` is assigned 10
2. Compiler evaluates `a++`, stores old value 10 and new value 11 as well. Since it's a post increment operation, assigns the old value to `a`. What i thought was, compiler would assign the old value 10 first and evaluate the `++` operation later. This is where i was wrong, compiler evaluates the RHS beforehand and assigns the value based on the operator.
4. 'a' is printed --> 10

Case 2:

1. `a` is assigned 10
2. Compiler evaluates `a++`, stores old value 10 and new value 11 as well. Since it's a post increment operation, assigns the old value to `c` but value of `a` is preserved with `11`.
4. 'a' is printed --> 11
like image 242
Sang Suantak Avatar asked Jan 17 '15 05:01

Sang Suantak


1 Answers

For me the best way to understand some behaviour is to check IL generated. In your first case it's

IL_0001:  ldc.i4.s    0A // stack: 10
IL_0003:  stloc.0     // a = 10, stack: empty
IL_0004:  ldloc.0     // stack: 10
IL_0005:  dup         // stack: 10, 10
IL_0006:  ldc.i4.1    // stack: 10, 10, 1
IL_0007:  add         // stack: 10, 11
IL_0008:  stloc.0     // a = 11, stack: 10
IL_0009:  stloc.0     // a = 10, stack: empty
IL_000A:  ldloc.0     // stack: 10
IL_000B:  call        System.Console.WriteLine

You can see that there's still that original value hanging on the stack and so the created 11 gets overwritten in the end.

Let me try to explain it in plain words.

When you are assigning a value to a variable (a = a++) the whole right side of the assignment gets evaluated first in order to guarantee the correct value, that's how it is. So nothing like you get 10, application goes on and increments value when you execute the next line.

Now, imagine post-increment as someone, who first increments a value, but gave you his world that you will get back the original value from the expression. And now you should see why the 11 is overwritten. Increment goes first and in the end, you get the promise original value (as IL proves).

like image 191
Ondrej Janacek Avatar answered Oct 06 '22 18:10

Ondrej Janacek