13

In an unchecked context, is adding one to an integer with the value 2147483647 guaranteed to result in -2147483648?

For example, with the following code

    const int first = int.MaxValue;
    int second = first;

    if ( second >= first )
    {
        Console.WriteLine( "First check" );
    }

    second++;

    if ( second >= first )
    {
        Console.WriteLine( "Second check" );
    }

In C++, it would be perfectly valid for both "First check" and "Second check" to be printed, as the optimizer can reuse the result of the first check for the second.

Is the same true of C#?

11
  • have you tried adding 1 to the number and inspecting it in the debugger.. it should yield -2147483648 Commented Oct 6, 2014 at 21:29
  • when it comes to .NET, there is really only one compiler Commented Oct 6, 2014 at 21:30
  • 1
    @DJKRAZE: That doesn't mean that the behavior is (or isn't) defined. Commented Oct 6, 2014 at 21:31
  • 4
    @Steve There are at least three compilers, all of which get used. Microsoft's original, Microsoft's Roslyn, and Mono's. Commented Oct 6, 2014 at 21:32
  • 3
    @Cory: The first implicitly answers the second. The only reason that a C++ optimizer could remove the second branch is because overflow of signed integers results in UB. So, the optimizer can assume that the increment did not overflow. In C# the behavior is defined and valid, so no such assumption can be made. Commented Oct 6, 2014 at 21:43

2 Answers 2

14

From the spec:

4.1.5 Integral Types

The checked and unchecked operators and statements are used to control overflow checking for integral-type arithmetic operations and conversions (§7.6.12). In a checked context, an overflow produces a compile-time error or causes a System.OverflowException to be thrown. In an unchecked context, overflows are ignored and any high-order bits that do not fit in the destination type are discarded.

That is the only description of the behavior that I could find, but it seems sufficient. So yes, adding one to Int32.MaxValue will result in the value Int32.MinValue using two's complement representation.

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

6 Comments

Does the spec also say that two's complement has to be used? I don't see that in §4.1.5.
@svick C# spec (5.0) says int is aliased to System.Int32. ECMA-335 (CLI) spec (6th ed) says System.Int32 is the class library type equivalent to the CIL assembly int32, which is defined as a "32-bit two’s-complement signed value". So, yes, assuming a compliant C# compiler and CIL implementation, C# ints must be two's complement (similar story for int8, int16 and int64).
please correct your assumption adding one to Int32.MaxValue will result in the value -1. its actually Int32.MinValue = -2147483648
Per this test, Int32.MaxValue+1 results in -2147483648 not -1.
@TakeMeAsAGuest Welll, I doubt I assumed anything. Only an ass would assume, as everyone knows. I don't remember why I wrote it, but I know what I wrote before it - "So, YES...". Emphasis mine, obvi. I dug out the representation and agree with the question, so seems like a stupid mistake. I can't know, for sure and I'd never assume. Like they say, assumptions make an ass out of you. Thanks for rhe catch.
|
1

MSDN:

For the arithmetic, casting, or conversion operation to throw an OverflowException, the operation must occur in a checked context. By default, arithmetic operations and overflows in Visual Basic are checked; in C#, they are not. If the operation occurs in an unchecked context, the result is truncated by discarding any high-order bits that do not fit into the destination type.

1 Comment

If you're quoting from some web page, you should link to it.

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.