java解惑之表达式之谜(谜题5)

来源:互联网 发布:黄一琳淘宝店质量如何 编辑:程序博客网 时间:2024/05/02 11:42

谜题5:十六进制的趣事

谜题由两个十六进制的常量相加而来,下面来看看示例程序代码:

public class JoyOfHex{

public static void main(String[] args){

System.out.println(0x100000000L + 0xcafebabe);

}

}

看似简单的相加计算打印出来的应该是1cafebabe,其实不然。该程序使用的是long类型的运算,支持16位十六进制数,因此排除运算溢出的可能。真正的打印结果是cafebabe,并没有任何前导的1,这个输出表示的是正确结果的低32位,但第33位确不知为何丢失了,那到底是什么原因导致第33位丢失的呢,下面我们来分析一下。

从程序中我们可以看出,左操作数是long类型的,而右操作数是int类型的,在计算过程中,需要把int类型转换成long类型,并且因为int是有符号的整数类型,所以这个转换执行的是符号扩展:将负的int类型数值提升为一个在数值上相等的long类型数值。即数值0xcafebabe是int常量,它的最高位被置位了(如果十六进制常量的最高位被置位了,那么它们就是负数),所以它是一个负数,它等于十进制数值的-889275714。因此,0xcafebabe被提升为long类型的数值0xffffffffcafebabe。当视为int类型时,经过符号扩展之后的右操作数的高32位是-1,而左操作数的高32位是1,两个数值相加得到了0,所以输出后的数值为cafebabe。避免这个错误发生只需要将右操作数表示成long类型即可,代码如下:

public class JoyOfHex{

public static void main(String[] args){

System.out.println(0x100000000L + 0xcafebabeL);

}

}

由此谜题得出在进行混合类型的计算可能会产生混淆,尤其需要注意的是十六进制和八进制字面常量无需显示的减号符号就可以表示负的数值。所以最好能避免混合类型的计算。

0 0