5

Why C# checked keyword does not treat -1 - int.MinValue as overflow?

int x = int.MinValue;
int y;

checked {
    // Overflow. 2^31 cannot be represented in signed integer.
    try { y = -x; } catch (OverflowException) { Console.WriteLine ("Overflow 1"); }

    // Overflow. Though the final result (2^31-1) fit in an integer, the intermediate value does not.
    try { y = -x-1; } catch (OverflowException) { Console.WriteLine ("Overflow 2"); }

    // No overflow. Please explain.
    try { y = -1-x; } catch (OverflowException) { Console.WriteLine ("Overflow 3"); }
}

Output:

Overflow 1
Overflow 2

Is this a bug in C# overflow checking, or something related to processor architecture?

2
  • 3
    It's probably worth adding a few details so the reader has to do less arithmetic. Like the fact that int.MinValue is -2,147,483,648 and -1-x is +2,147,483,647 but -x is +2,147,483,648 (which doesn't fit into an int). So really you're asking why -x-1 overflows but -1-x doesn't. Well, since operations go left to right, it should be more evident. Negating x causes an overflow, but sub(-1, x) doesn't. Commented Sep 9 at 19:36
  • 1
    I pasted the program in sharplab.io. C# translates the first expression to sub.ovf(0, x), and second one to sub.ovf(sub.ovf(0, x), 1). In both expressions, sub.ovf(0, x) appears which causes the overflow. For the last one, it's simply sub.ovf(-1, x) which produces a results within Int32 bounds, hence no overflow. Commented Sep 9 at 19:50

2 Answers 2

17

In example 1 and 2, you have unary operator - in front of x. It has highest precedence, so the negating operation is first and throws.

In example 3, you have binary operator - in front of x. The result of the subtraction is not overflowing, it's 2147483647 which fits int32.

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks for the explanation. Maybe the large numbers blew up my mind. To explain you the confusion, let's assume that integers have range from -10 (min value) to +9 (max value). I was subconsciously solving the expression (-1-(-10)) the way we do it by hand i.e. fix the signs to get (-1+10) first and then get to the answer: 9. But for the computer, it's a single operation.
6

It's just math - that Int.MinSize is a negative number and you're subtracting it. Let's use 32 bit numbers.

Int32.MinValue= -2147483648
Int32.MaxValue= 2147483,647

-1 - (-2147483648) = 2147483,647

You end up precisely with the value of Int.MaxValue, so there is no overflow.

2 Comments

I feel like a proper answer needs to address the fact that the asker's misunderstanding appears to come from the fact that -1-x and -x-1 appear to be equivalent from a mathematical standpoint, but in C# the expressions are different. One negates x the other does not -- it performs a subtraction where x is the second operand.
That's right, the result of each operation needs to fit into the data type - and the negation attempts to store a value greater than the MaxValue.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.