Шестнадцатеричные литералы, ошибка компилятора или плохо написанные спецификации? - PullRequest
4 голосов
/ 09 февраля 2012

В спецификации Scala написано

1.3.1 Целочисленные литералы

Синтаксис:

integerLiteral ::= (decimalNumeral | hexNumeral | octalNumeral) [‘L’ | ‘l’]
decimalNumeral ::= ‘0’ | nonZeroDigit {digit}
hexNumeral     ::= ‘0’ ‘x’ hexDigit {hexDigit}
octalNumeral   ::= ‘0’ octalDigit {octalDigit}
digit          ::= ‘0’ | nonZeroDigit
nonZeroDigit   ::= ‘1’ | · · · | ‘9’
octalDigit     ::= ‘0’ | · · · | ‘7’

Целочисленные литералы обычно имеют тип Int или тип Long, за которым следует L или l суффикс. Значения типа Int представляют собой целые числа от -2 31 до 2 31 -1 включительно. Значения типа Long представляют собой целые числа от -2 63 до 2 63 -1 включительно. Ошибка времени компиляции происходит, если целочисленный литерал обозначает число вне этих Диапазоны

Последний раз, когда я проверял 0x80000000, равен 2147483648, который должен быть вне диапазона для Int ( "между -2 31 и 2 31 -1, включено ").

Тем не менее компилятор не жалуется, а вместо этого позволяет целочисленному переполнению в -2147483648.

Итак, спецификация неверна, компилятор неверен или я что-то неправильно понял?

Редактировать: То же число, записанное в десятичной форме, обрабатывается правильно и выдает ошибку.

Ответы [ 3 ]

3 голосов
/ 09 февраля 2012

Старший значащий бит в целом числе со знаком используется для обозначения знака, а не большой степени 2 - таким образом, все с этим установленным битом будет представлять отрицательное, а не положительное число. Используется форма two'splement , что означает, что 0x8000000 действительно равно -2147483648.

Для редактирования: по той же причине в десятичном виде записано -2147483638, а не +2147483638.

2 голосов
/ 09 февраля 2012

Как указывает Дейв , " поведение Scala в этом отношении идентично Java. "

Что наводит меня на мысль, что Scala выбрали интерпретацию Java относительно целочисленных литералов все вместе.

Это поведение достаточно хорошо описано в спецификации языка Java, Раздел 3.10.1. Целочисленные литералы :

Наибольшие положительные шестнадцатеричные и восьмеричные литералы типа int равны 0x7fffffff и 017777777777 соответственно, что равно 2147483647 (2 31 -1). Наиболее отрицательными шестнадцатеричными и восьмеричными литералами типа int являются 0x80000000 и 020000000000 соответственно, каждый из которых представляет десятичное значение -2147483648 (-2 31 ). Шестнадцатеричные и восьмеричные литералы 0xffffffff и 037777777777, соответственно, представляют десятичное значение -1. ​​

В целом, я бы сказал, что спецификация неявно наследует спецификацию Java для частей, которые равны и в некотором роде очевидны, и являются явными только для частей, которые (могут) отличаться, например, синтаксис (язык синтаксически сильно отличается от Java).

1 голос
/ 09 февраля 2012

Беззнаковые числа в шестнадцатеричной форме из 2 31 и 2 32 -1 автоматически преобразуются в отрицательные числа, соответствующие их двоичному представлению, для Int,Отрицательные числа в этом диапазоне (кроме -2 31 ) молча преобразуются в их дополнение-2, которое превращается в положительные числа.Эквивалентное правило применяется для Long.ИМХО, спецификация должна сказать так, но я не проверял, если это так.

Компилятор действительно жалуется на числа вне этого диапазона.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...