【问题标题】:negative char Value JAVA负字符值 JAVA
【发布时间】:2013-02-17 00:53:31
【问题描述】:

为什么会这样:

char p = 0;
p--;
System.out.println(p);

结果65535

为什么不给出编译错误或运行时异常? 我期望它,因为字符不能为负数。相反,它从倒挂开始倒数。 提前致谢。

【问题讨论】:

  • 这只是一个很好的无符号短片。

标签: java char int


【解决方案1】:

为什么不给它一个编译错误或运行时异常?

因为语言规范要求基本类型的算术运算以 2^width 为模,所以 -1 变为 2^16-1char

the section on integer operations 中声明

内置的整数运算符不会以任何方式指示上溢或下溢。

这样就禁止抛出异常。

对于使用的后缀自减运算符,具体而言,其行为在15.14.3中指定

否则,从变量的值中减去值 1,并将差值存储回变量中。在减法之前,对值 1 和变量的值执行二进制数字提升(第 5.6.2 节)。如有必要,可通过缩小原语转换(第 5.1.3 节)和/或在存储变量之前对其类型进行装箱转换(第 5.1.7 节)来缩小差异。后缀递减表达式的值是变量在新值存储之前的值。

二进制数值提升将值和 1 都转换为 int(因为这里的类型是 char),因此您有中间结果 -1 作为 int,然后是缩小原语转换执行:

有符号整数到整数类型 T 的窄化转换只会丢弃除 n 个最低位之外的所有位,其中 n 是用于表示类型 T 的位数。除了可能丢失有关数值,这可能会导致结果值的符号与输入值的符号不同。

导致char 的值为0xFFFF(因为Java 为其有符号整数类型指定了二进制补码表示,在unary minus 的规范中明确说明):

对于整数值,求反与从零减法相同。 Java 编程语言对整数使用二进制补码表示,二进制补码值的范围不是对称的,因此最大负 int 或 long 的取反会产生相同的最大负数。这种情况下会发生溢出,但不会抛出异常。对于所有整数值 x,-x 等于 (~x)+1。

对于超出范围结果的一般环绕行为,例如in the specification of the multiplication operator

如果整数乘法溢出,则结果是数学乘积的低位,以某种足够大的二进制补码格式表示。因此,如果发生溢出,则结果的符号可能与两个操作数值的数学乘积的符号不同。

在整数加法的规范中出现类似的短语,需要减法来满足a - b == a + (-b),所以溢出行为如下。

【讨论】:

  • 你有可以引用的参考资料吗?
  • 给我一分钟谷歌一下,我这里没有规格。
【解决方案2】:

因为这就是 Java 语言的定义方式。运行时不会检查每个操作的边界(可能是因为它会非常昂贵)。它只是上溢或下溢。

【讨论】:

    猜你喜欢
    • 2015-01-09
    • 1970-01-01
    • 1970-01-01
    • 2019-04-14
    • 1970-01-01
    • 1970-01-01
    • 2018-06-24
    • 2021-11-15
    相关资源
    最近更新 更多