4

我对 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*/

为什么 ?

4

7 回答 7

8

这是Java语言规范方面的解释。

关于整数文字的部分(JLS 3.10.1)说:

int 类型的最大十进制文字是2147483648(2 31 )。0从to的所有十进制文字2147483647可能出现在任何可能出现 int 文字的地方,但文字2147483648可能仅作为一元否定运算符的操作数出现-

所以 ...

  • 第一条语句是一个合法整数文字值的赋值。没有编译错误。

  • 第二条语句是编译错误,因为2147483648前面没有一元否定运算符。

  • 第三条语句不包含超出范围的整数文字,因此从这个角度来看,它不是编译错误。

相反,第三条语句是JLS 15.18.2中描述的二进制加法表达式。这说明了有关整数情况的以下内容:

如果整数加法溢出,则结果是数学和的低位,以一些足够大的二进制补码格式表示。如果发生溢出,则结果的符号与两个操作数值的数学和的符号不同。

因此,2147483647 + 1溢出并环绕到-2147483648.


@Peter Lawrey 建议(轻率地?)第三条语句可以“由编译器重写”为+2147483648,从而导致编译错误。

这是不正确的。

JLS 中没有任何内容表明常量表达式可以与非常量表达式具有不同的含义。相反,在1 / 0JLS 之类的情况下,会翻转并说表达式不是常量表达式,因为它异常终止。(在JLS 15.28中)

JLS 非常努力地避免某些 Java 构造意味着不同事物的情况,具体取决于编译器。例如,它对“明确赋值”规则非常讲究,以避免只有智能编译器才能推断出变量总是在使用之前被初始化的情况。从代码可移植性的角度来看,这是一件好事。

The only significant area where there is "wiggle room" for compiler implementers to do platform specific things is in the areas of concurrency and the Java memory model. And there is a sound pragmatic reason for that - to allow multi-threaded Java applications to run fast on multi-core / multi-processor hardware.

于 2011-02-28T10:13:42.697 回答
2

int范围从Integer.MIN_VALUE(-2147483648)Integer.MAX_VALUE(2147483647)

但是,仅int根据范围检查文字。

Java 不检查任何给定的常量值表达式是否适合该范围。

“允许”计算通过这些边界,但这将导致溢出(即仅存储结果值的低位)。因此,计算在计算2147483647 + 1 中是明确定义的int,它是 -2147483648。

于 2011-02-28T09:38:06.403 回答
1

因为第三种叫做整数溢出。你正在做计算并且你溢出了。其他的只是常数。

于 2011-02-28T09:35:07.240 回答
1

因为

int z=2147483647+1;

会溢出,不等于2147483648

于 2011-02-28T09:36:22.230 回答
1

前两种情况似乎很明显。第三种情况会默默溢出。因此,在这种情况下,您应该始终在调用代码中处理它。

于 2011-02-28T09:39:19.970 回答
0

第三个表达式是基于 int 的加法,因此它将结果转换为 int 范围内的值。

于 2011-02-28T09:36:53.070 回答
0

的范围int是。Java 会悄悄地溢出,因此编译器不会检测到计算结果。(但可能会被您的 IDE 检测到)Integer.MIN_VALUEInteger.MAX_VALUE

最令人惊讶的溢出操作之一是-Integer.MIN_VALUE

于 2011-02-28T09:36:56.323 回答