十六进制文字,编译器错误或编写错误的规范?

时间:2012-02-09 11:05:02

标签: scala overflow

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后跟Ll   后缀。 Int类型的值都是-2 31 和2 31 -1之间的整数,包括端值。 Long类型的值都是-2 63 和2 63 -1之间的整数,包括端值。   如果整数文字表示这些之外的数字,则会发生编译时错误   范围

上次我检查0x80000000等于2147483648,这应该超出Int的范围(“介于-2 31 和2 31 < / sup> -1,包含“)。

编译器仍然抱怨,而是让整数溢出到-2147483648。

那么,规范是错误的,编译器是错误的,还是我误解了什么?

编辑:以十进制形式编写的相同数字会被正确处理并产生错误。

3 个答案:

答案 0 :(得分:3)

有符号整数中的最高有效位用于指示符号,而不是2的高功率 - 因此,设置此位的任何内容都将表示负数,而不是正数。使用two's complement形式,意味着0x8000000确实等于-2147483648。

编辑:由于同样的原因,以十进制写的相同数字是-2147483638,而不是+2147483638。

答案 1 :(得分:2)

正如dave所指出的,&#34; Scala在这方面的行为与Java相同。&#34;

这让我相信Scala已经选择了Java关于整数文字的解释。

Java语言规范Section 3.10.1 Integer Literals中很好地涵盖了这种行为:

  

int类型的最大正十六进制和八进制文字分别为0x7fffffff017777777777,等于2147483647(2 31 - 1)。类型int的最负十六进制和八进制文字分别是0x80000000020000000000,每个都代表十进制值-2147483648(-2 31 ) 。十六进制和八进制文字0xffffffff037777777777分别代表十进制值-1。

总而言之,我说该规范隐含地继承了Java的规范,用于相同且有点明显的部分,并且只对那些部分明确表示(可能)不同,例如语法(语言毕竟在语法上与Java完全不同)。

答案 2 :(得分:1)

来自2 31 和2 32 -1的无符号数字以十六进制格式被静默转换为对应于其二进制表示的负数, Int。该范围内的负数(除了-2 31 )被无声地转换为它们的补体-2,其包含在正数中。等效规则适用于Long。恕我直言,规范应该这样说,但我没有检查是否有。

编译器会抱怨此范围之外的数字。