tags:

views:

150

answers:

8

Consider this

        int i = 2147483647;
        var n = i + 3;
        i = n;

        Console.WriteLine(i);           // prints -2147483646    (1)
        Console.WriteLine(n);           // prints -2147483646    (2)
        Console.WriteLine(n.GetType()); // prints System.Int32   (3)

I am confused with following

  • (1) how could int hold the value -2147483646 ? (int range = -2,147,483,648 to 2,147,483,647)
  • (2) why does this print -2147483648 but not 2147483648 (compiler should decide better type as int range exceeds)
  • (3) if it is converted somewhere, why n.GetType() gives System.Int32 ?

Edit1: Made the correction: Now you will get What I am Getting. (sorry for that)

var n = i + 1; to

var n = i + 3;

Edit2: One more thing, if it as overflow, why is an exception not raised ?

Addition: as the overflow occurs, is it not right to set the type for

var n

in statement var n = i + 3; to another type accordingly ?


you are welcome to suggest a better title, as this is not making sense to.... me at least

Thanks

+6  A: 

Update: Poster fixed his question.

1) This is output is expected because you added 3 to int.MaxValue causing an overflow. In .NET by default this is a legal operation in unchecked code giving a wrap-around to negative values, but if you add a checked block around the code it will throw an OverflowException instead.

2) The type of a variable declared with var is determined at compile time not runtime. It's a rule that adding two Int32s gives an Int32, not a UInt32, an Int64 or something else. So even though at runtime you can see that the result is too big for an Int32, it still has to return an Int32.

3) It's not converted to another type.

Mark Byers
+1  A: 
  1. This is an overflow, your number wrapped around and went negative
  2. This isn't the compiler's job, as a loop at runtime can cause the same thing
  3. int is an alias or System.Int32 they are equivalent in .Net.
Nick Craver
+3  A: 
 1)  -2147483646 is bigger than -2,147,483,648
 2) 2147483648 is out of range
 3) int is an alias for Int32
Otávio Décio
+3  A: 

1)
First of all, the value in the variable is not -2147483646, it's -2147483648. Run your test again and check the result.

There is no reason that an int could not hold the value -2147483646. It's within the range -2147483648..2147483647.

2)
The compiler chooses the data type of the variable to be the type of the result of the expression. The expression returns an int value, and even if the compiler would choose a larger data type for the variable, the expression still returns an int and you get the same value as result.

It's the operation in the expression that overflows, it's not when the result is assigned to the variable that it overflows.

3)
It's not converted anywhere.

Guffa
+1 for being the first to actual take the whole `var` thing into account, which I think was the real problem of the OP. `var` doesn't mean "figure out what type is the most appropriate to use here". It literally means "I'm too lazy of figuring out what type your input is, so do it for me". That doesn't mean using `var` is bad, but you need to understand what it does if you want to use it properly.
Michael Madsen
+1  A: 

This is because of the bit representation

you use Int32 but the same goes for char (8 bits)

the first bit holds the sign, then the following bits hold the number

so with 7 bits you can represent 128 numbers 0111 1111

when you try the 129th, 1000 0001, the sign bits get set so the computer thinks its -1 instead

A: 

Arithmic operations in .NET don't change the actual type.
You start off with an (32bit) integer and the +3 isn't going to change that.

That's also why you get an unexpected round number when you do this:

int a = 2147483647;
double b = a / 4;

or

int a = 2147483647;
var b = a / 4;

for that matter.

EDIT:
There is no exception because .NET overflows the number.
The overflow exception will only occur at assignment operations or as Mark explains when you set the conditions to generate the exception.

Zyphrax
A: 

You could make this easier on us all by using hex notation.

Not everyone knows that the eighth Mersenne prime is 0x7FFFFFFF

Just sayin'

Mawg
A: 

If you want an exception to be thrown, write

abc = checked(i+3)

instead. That will check for overflows.

Also, in c#, the default setting is to not throw exceptions on overflows. But you can switch that option somewhere on your project's properties.

devoured elysium