2010-02-14 2 views
3

Рассмотрим этотINT или UINT или что

 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) 

Я запутался со следующими

  • (1) как можно ИНТ хранить значение -2147483646? (Диапазон INT = -2147483648 до 2147483647)
  • (2) почему это печать -2147483648 но не 2147483648 (компилятор должен решить лучший тип, как INT диапазон превышает)
  • (3), если он преобразуется где-то, почему n.GetType() дает System.Int32 ?

Edit1: Сделано исправление: Теперь вы получите то, что я получаю. (извините за это)

var n = i + 1; до

var n = i + 3;

Edit2: Еще одна вещь, если она перетекала, почему исключение не воскресают?

Дополнение: как это происходит переполнение, это не правильно установить тип для

вар п

в заявлении var n = i + 3; другого типа соответственно?


вы можете предложить лучшее название, так как это не делает смысл .... мне, по крайней мере

Благодаря

+0

За что голосовать? –

ответ

6

Update: Poster устремил вопрос.

1) Ожидается, что это результат, потому что вы добавили 3 к int.MaxValue, вызывая переполнение. В .NET по умолчанию это законная операция в непроверенном коде, дающая обертку отрицательным значениям, но если вы добавите блок checked вокруг кода, он вместо этого выкинет OverflowException.

2) Тип переменной, объявленной с var, определяется во время компиляции, а не во время выполнения. Это правило, что добавление двух Int32s дает Int32, а не UInt32, Int64 или что-то еще. Таким образом, хотя во время выполнения вы видите, что результат слишком велик для Int32, он все равно должен вернуть Int32.

3) Он не преобразован в другой тип.

1
  1. This is an overflow, номер обернута вокруг и пошел отрицательный
  2. Это не работа компилятора, как цикл во время выполнения может вызвать то же самое
  3. int является псевдонимом или System.Int32 они эквивалентны. Сеть.
3
1) -2147483646 is bigger than -2,147,483,648 
2) 2147483648 is out of range 
3) int is an alias for Int32 
3

1)
Прежде всего, значение переменной не -2147483646, это -2147483648. Повторите тест и проверьте результат.

Нет никакой причины, чтобы int не мог удерживать значение -2147483646. Он находится в пределах диапазона -2147483648..2147483647.

2)
Компилятор выбирает тип данных переменной как тип результата выражения. Выражение возвращает значение int, и даже если компилятор будет выбирать более крупный тип данных для переменной, выражение все равно возвращает int, и вы получите то же значение, что и результат.

Это операция в выражении, которое переполняется, это не когда результат присваивается переменной, которая переполняется.

3)
Это не преобразовано нигде.

+0

+1 для того, чтобы быть первыми, кто принимал во внимание всю вещь 'var', что я считаю реальной проблемой OP. 'var' не означает« выяснить, какой тип наиболее подходит для использования здесь ». Это буквально означает: «Я слишком ленив, чтобы понять, какой тип ввода, так что сделайте это для меня». Это не означает, что использование «var» - это плохо, но вам нужно понять, что он делает, если вы хотите использовать его правильно. –

1

Это из-битового представления

вы используете Int32, но то же самое для полукокса (8 бит)

первый бит держит знак, то следующие биты содержат номер

так с 7 битами можно представить 128 номеров 0111 1111

при попытке 129-го, 1000 0001, знаковые биты получить установлены таким образом, компьютер думает что -1 вместо

0

Арифметические операции в .NET не изменяют фактический тип.
Вы начинаете с целого числа (32 бит), а +3 не изменит это.

Это также объясняет, почему вы получите неожиданное круглое число, когда вы делаете это:

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

или

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

по этому вопросу.

EDIT:
Там не исключение, потому что .NET переполняется число.
Исключение переполнения будет происходить только при выполнении операций присваивания или, как объясняет Марк, когда вы устанавливаете условия для генерации исключения.

0

Вы можете сделать это проще для всех нас, используя шестнадцатеричную нотацию.

Не все знают, что восьмой Мерсенна является 0x7FFFFFFF

Просто говорю

0

Если вы хотите исключение выбросить, написать

abc = checked(i+3) 

вместо этого. Это проверит переполнение.

Кроме того, в C# значение по умолчанию не должно исключать исключения при переполнении. Но вы можете переключить эту опцию где-нибудь на свойства вашего проекта.

Смежные вопросы