Search code examples
c#operatorsoperator-precedence

How does the pre/post-increment operator behave before variable allocation?


int x=3, y=4, n=0;
int n = x * y / --x;

This code calculates n to be 6, but I thought it'd be 4; since --x is a pre-decrement operator and has higher precedence than * and / so it would be 2 * 4 / 2 I assumed it's 2*4 and not 3*4 as x has already been decremented, so what am I missing here? The same question has been asked here but the answer was PHP-specific.


Solution

  • If we compile this code and then inspect it using ildasm, we get the following instructions (translated using https://en.wikipedia.org/wiki/List_of_CIL_instructions):

     IL_0000:  nop          // I compiled in debug mode, this does nothing
     IL_0001:  ldc.i4.3     // Push 3 onto the stack as int32.  
     IL_0002:  stloc.0      // Pop a value from stack into local variable 0.
     IL_0003:  ldc.i4.4     // Push 4 onto the stack as int32.  
     IL_0004:  stloc.1      // Pop a value from stack into local variable 1.
     IL_0005:  ldloc.0      // Load local variable 0 onto stack.
     IL_0006:  ldloc.1      // Load local variable 1 onto stack.
     IL_0007:  mul          // Multiply values.
     IL_0008:  ldloc.0      // Load local variable 0 onto stack.
     IL_0009:  ldc.i4.1     // Push 1 onto the stack as int32.  
     IL_000a:  sub          // Subtract value2 from value1, returning a new value.
     IL_000b:  dup          // Duplicate the value on the top of the stack.
     IL_000c:  stloc.0      // Pop a value from stack into local variable 0.    
     IL_000d:  div          // Divide two values to return a quotient or floating-point result. 
     IL_000e:  stloc.2      // Pop a value from stack into local variable 2.
     IL_000f:  ret          // Return from method, possibly with a value.   
    

    This reveals that the expression is evaluated from left to right, even though --x precedes * and /.

    This is also documented in the C# language specification (section 7.3 Operators):

    The order of evaluation of operators in an expression is determined by the precedence and associativity of the operators (§7.3.1).

    Operands in an expression are evaluated from left to right. For example, in F(i) + G(i++) * H(i), method F is called using the old value of i, then method G is called with the old value of i, and, finally, method H is called with the new value of i. This is separate from and unrelated to operator precedence.