The expression int.Minvalue / -1
results in implementation defined behavior according to the C# specification:
7.8.2 Division operator
If the left operand is the smallest representable int or long value and the right operand is –1, an overflow occurs. In a checked context, this causes a System.ArithmeticException (or a subclass thereof) to be thrown. In an unchecked context, it is implementation-defined as to whether a System.ArithmeticException (or a subclass thereof) is thrown or the overflow goes unreported with the resulting value being that of the left operand.
Test program:
var x = int.MinValue;
var y = -1;
Console.WriteLine(unchecked(x / y));
This throws an OverflowException
on .NET 4.5 32bit, but it does not have to.
Why does the specification leave the outcome implementation-defined? Here's the case against doing that:
- The x86
idiv
instruction always results in an exception in this case. - On other platforms a runtime check might be necessary to emulate this. But the cost of that check would be low compared to the cost of the division. Integer division is extremely expensive (15-30 cycles).
- This opens compatibility risks ("write once run nowhere").
- Developer surprise.
Also interesting is the fact, that if x / y
is a compiletime constant we indeed get unchecked(int.MinValue / -1) == int.MinValue
:
Console.WriteLine(unchecked(int.MinValue / -1)); //-2147483648
This means that x / y
can have different behaviors depending on the syntactic form being used (and not only depending on the values of x
and y
). This is allowed by the specification but it seems like an unwise choice. Why was C# designed like this?
A similar question points out where in the specification this exact behavior is prescribed but it does not (sufficiently) answer why the language was designed this way. Alternative choices are not discussed.