сомнение с диапазоном переменной int - PullRequest
4 голосов
/ 28 февраля 2011

У меня есть сомнения с диапазоном значения int

int x=2147483647;     /*NO Error--this number is the maximum range 
                        of int value no error*/
int y=2147483648;     /*Error--one more than the
                        maximum range of int*/
int z=2147483647+1;  /*No Error even though it is one more
                       than the maximum range value*/

почему?

Ответы [ 7 ]

8 голосов
/ 28 февраля 2011

Вот объяснение в терминах спецификации языка Java.

Раздел целочисленных литералов ( JLS 3.10.1 ) гласит:

Самый большой десятичный литерал типа int равен 2147483648 (2 31 ). Все десятичные литералы от 0 до 2147483647 могут появляться везде, где может появляться литерал int, но литерал 2147483648 может появляться только как операнд унарного оператора отрицания -.

Итак ...

  • Первое утверждение - это присвоение допустимого целочисленного литерального значения. Нет ошибки компиляции.

  • Вторым оператором является ошибка компиляции, поскольку 2147483648 не предшествует унарный оператор отрицания.

  • Третье выражение не содержит целочисленного литерала, выходящего за пределы допустимого диапазона, поэтому с этой точки зрения это не ошибка компиляции.

Вместо этого третье выражение является двоичным выражением сложения, как описано в JLS 15.18.2 . Это заявляет следующее о целочисленном регистре:

Если целочисленное сложение переполняется, то результатом являются младшие биты математической суммы, представленные в некотором достаточно большом формате с двумя дополнениями. Если происходит переполнение, то знак результата не совпадает со знаком математической суммы двух значений операнда.

Таким образом, 2147483647 + 1 переполняется и переходит в -2147483648.


@ Питер Лори предлагает (легкомысленно?), Что третье утверждение может быть «переписано компилятором» как +2147483648, что приведет к ошибке компиляции.

Это не правильно.

В JLS нет ничего, что говорило бы, что константное выражение может иметь значение, отличное от непостоянного выражения. Напротив, в случаях, подобных 1 / 0, JLS переворачивает и говорит, что выражение НЕ является константным выражением, ПОТОМУ ЧТО оно заканчивается ненормально. (Находится в JLS 15,28 )

JLS очень старается избегать случаев, когда некоторые Java-конструкции означают разные вещи, в зависимости от компилятора. Например, это очень строго относится к правилам «определенного присваивания», чтобы избежать случая, когда только умный компилятор может определить, что переменная всегда инициализируется перед ее использованием. Это хорошая вещь с точки зрения переносимости кода.

Единственная существенная область, где есть «пространство для маневра» для разработчиков компиляторов для выполнения специфичных для платформы вещей, находится в областях параллелизма и модели памяти Java. И для этого есть веская прагматичная причина - позволить многопоточным приложениям Java быстро работать на многоядерном / многопроцессорном оборудовании.

2 голосов
/ 28 февраля 2011

int в диапазоне от Integer.MIN_VALUE (-2147483648) до Integer.MAX_VALUE (2147483647) .

Однако проверяются только литералы intпротив диапазона.

Java не проверяет, что любое заданное выражение константного значения вписывается в диапазон.

Вычислениям "разрешено" проходить эти границы, но это приведет к переполнению (т.е.будут сохранены только младшие биты результирующего значения).Следовательно, расчет 2147483647 + 1 четко определен в вычислениях int, и он равен -2147483648.

1 голос
/ 28 февраля 2011

Первые два случая кажутся очевидными. Третий случай тихо переполнится. Поэтому в таких случаях вы всегда должны обрабатывать это в своем коде вызова.

1 голос
/ 28 февраля 2011

Потому что

int z=2147483647+1;

будет переполнено, что не равно 2147483648

1 голос
/ 28 февраля 2011

Потому что третий называется целочисленным переполнением. Вы делаете вычисления, и вы переполнены. Остальные просто константы.

0 голосов
/ 28 февраля 2011

Диапазон для int составляет от Integer.MIN_VALUE до Integer.MAX_VALUE.Java плавно переполняется, поэтому компилятор не обнаруживает результат вычисления.(Но может быть обнаружен вашей IDE)

Одна из самых удивительных операций переполнения - -Integer.MIN_VALUE

0 голосов
/ 28 февраля 2011

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

...