java中移位运算-vb 移位运算
说明:本文主要摘录自《深入理解计算机系统》第二章信息的表示与处理。
移位运算:
C语言还提供了一组移位运算,以便向左或者向右移动位模式。对于一个位表示为[xn-1,xn-2,…,x0]的操作数x,C表达式x>k,但是它的行为有点微妙。一般而言,机器支持两种形式的右移:逻辑右移和算术右移。逻辑右移在左端补k个0,得到的结果是[0,…,0,xn-1java中移位运算,xn-2,…,xk]。算术右移是在左端补k个最高有效位的值,得到的结果是[xn-1,…,xn-1,xn-1,xn-2java中移位运算,…,xk]。这种做法看上去可能有点奇特,但是我们会发现它对有符号整数数据的运算非常有用。
让我们来看一个例子,下面的表给出了对某些实例8位数据做不同的移位操作得到的结果。
操作
值
参数X
[0110 0011] [1001 0101]
X>4(逻辑右移)
[0000 0110] [0000 1001]
X>>4(算术右移)
[0000 0110] [1111 1001]
斜体的数字表示的是最右端(左移)或最左端(右移)填充的值。可以看到除了一个条目之外,其他的都涉及填充0。唯一的例外是算术右移[10010101]的情况。因为操作数的最高位是1,填充的值就是1。
C语言标准并没有明确定义应该使用哪种类型的右移。对于无符号数据(也就是以限定词unsigned声明的整型对象),右移必须是逻辑的。而对于有符号数据(默认的声明的整型对象),算术的或者逻辑的右移都可以。不幸的是,这就意味着任何假设一种或者另一种右移形式的代码都潜在着可移植性问题。然而,实际上,几乎所有的编译器/机器组合都对有符号数据使用算术右移,且许多程序员也都假设机器会使用这种右移。
另一方面,Java对于如何进行右移有明确的定义。表达式x>>k会将x算术右移k个位置,而x>>>k会对x做逻辑右移。
当移动k位,这里k很大时
对于一个由w位组成的数据类型,如果要移动k≥w位会得到什么结果呢?例如,在一个32位机器上计算下面的表达式会得到什么结果:
Int lval = 0xFEDCBA98 > 36
unsigned lval = 0xFEDCBA98u >> 40;
C语言标准很小心地规避了说明在这种情况下该如何做。在许多机器上,当移动一个w位的值时,移位指令只考虑位移量的低log2w位,因此实际上位移量就是通过计算k mod w得到的。例如,在一台采用这个规则的32位机器上,上面三个移位运算分别是移动0、4和8位,得到结果:
Lval 0xFEDCBA98
Aval 0xFEDCBA9
Uval 0x00FEDCBA
不过这种行为对于C程序来说是没有保证的,所以移位数量应该保持小于字长。另一方面,Java特别要求位移数量应该按照我们前面所讲的求模的方法来计算。
与移位运算有关的操作符优先级问题
常常有人会写这样的表达式1