0
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.

Community
  • 1
  • 1
Abdelrahman Eid
  • 881
  • 2
  • 13
  • 28
  • http://stackoverflow.com/questions/2371118/how-do-the-post-increment-i-and-pre-increment-i-operators-work-in-java – kbunarjo Dec 28 '16 at 18:20
  • @kbunarjo That doesn't answer my question. – Abdelrahman Eid Dec 28 '16 at 18:21
  • x has already been evaluated before it gets to --x, therefore x is still 3. – kbunarjo Dec 28 '16 at 18:25
  • But `--` has higher precedence than `*` and therefore `--x` is evaluated before going to `x*y`, isn't that correct? – Abdelrahman Eid Dec 28 '16 at 18:27
  • I believe that c++ is first evaluates the variable names before doing any arithmetic. Therefore when it comes upon the first x, it evaluates that as 3, and then moves on the the y, and then the --x, which it appropriately decrements. Then it does the arithmetic. – kbunarjo Dec 28 '16 at 18:30
  • 1
    Are you sure about that? That's C# by the way. Now speaking about C++ I went ahead and tried this in Xcode it gives me a warning: "Unsequenced modification and access to 'x'". – Abdelrahman Eid Dec 28 '16 at 18:39
  • It has a higher precedence in the fact it decremented before it divided. I wouldn't have expected it to decrement before the multiply because `--x` wasn't to be used until the divide. – TyCobb Dec 28 '16 at 18:59
  • 1
    The C# specification is very clear that associativity, precendence, and order of evalution are all different things. Expressions like `x`, `y`, and `--x` are evaluated from left to right. I'm sure there's a duplicate of this question. – Mike Zboray Dec 28 '16 at 19:25
  • @mike Associativity comes into play when we have two operators with the same precedence. Now what to do you mean by 'evaluated from right t left'? Do you mean associativity? If so they don't have the same precedence, if not then what use is the precedence if operators with different precedence is always evaluated LTR? – Abdelrahman Eid Dec 28 '16 at 19:33
  • [This article](https://blogs.msdn.microsoft.com/ericlippert/2008/05/23/precedence-vs-associativity-vs-order/) is a good one that explains the difference between the three concepts and contrasts C# with C++. – Mike Zboray Dec 28 '16 at 19:33

1 Answers1

2

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.

mstaessen
  • 1,227
  • 11
  • 16
  • Can you please give an example of LTR evaluation not using functions, just operators? – Abdelrahman Eid Dec 28 '16 at 19:39
  • 1
    Your example is one. The operands are evaluated LTR (`x`, then `y`, then `--x`). The order of _operations_ is determined by operator precedence but the _operands_ themselves are evaluated left-to-right. – D Stanley Dec 28 '16 at 19:55
  • What @D Stanley wrote was exactly what I was going to say. There is a difference between operands and operators. Operator precedence defines the order in which the operands are processed, but before processing the expression, all operandes are evaluated from left to right, regardless of the operators in the expression. – mstaessen Dec 28 '16 at 20:00