怀疑int变量的范围

时间:2011-02-28 09:32:46

标签: java integer-overflow

我对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 个答案:

答案 0 :(得分:8)

以下是Java语言规范的解释。

关于整数文字(JLS 3.10.1)的部分说明了这一点:

  

int类型的最大十进制文字是2147483648(2 31 )。从02147483647的所有小数文字都可能出现在int文字可能出现的任何位置,但文字2147483648可能仅作为一元否定运算符-的操作数出现。 / p>

所以......

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

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

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

相反,第三个语句是JLS 15.18.2中描述的二进制加法表达式。这表示以下关于整数的情况:

  

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

因此,2147483647 + 1溢出并包裹到-2147483648


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

这不正确。

JLS中没有任何内容表明常量表达式与非常量表达式具有不同的含义。相反,在像1 / 0这样的情况下,JLS会翻转事物并表示表达式不是常量表达式,因为它会异常终止。 (它在JLS 15.28

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

对于编译器实现者来说,做平台特定事情的“摆动空间”的唯一重要领域是并发和Java内存模型。这有一个合理的实用理由 - 允许多线程Java应用程序在多核/多处理器硬件上快速运行。

答案 1 :(得分:2)

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

但是,只会根据范围检查int个文字。

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

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

答案 2 :(得分:1)

因为第三个称为整数溢出。你正在进行计算而且你会溢出。其他的只是常数。

答案 3 :(得分:1)

因为

int z=2147483647+1;

会溢出,不等于2147483648

答案 4 :(得分:1)

前两个案例似乎很明显。第三种情况将无声地溢出。所以在这种情况下,你应该总是在你的调用代码中处理它。

答案 5 :(得分:0)

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

答案 6 :(得分:0)

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

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