在很多语言(如:C和Java)中都提供了移位运算,它包括:左移运算和右移运算两种。
其中,左移运算(<<)比较简单和固定,X向左移k位,即是丢弃最左端的k位,并在右端补k个0。
而右移运算有两种类型,一种是叫逻辑右移,另一种是算术右移。X右移k位这个操作,在逻辑右移中,为舍弃最右端的k位,并在左端补k个0,而在算术右移中,它表示为在左端补k个最高有效位的值(可能是0也可能是1)。
在C语言中,右移运算统一表示为 X>>k,C语言标准没有明确定义应该使用哪种类型的右移。对于无符号数据,右移必须是逻辑右移。而对于有符号数据,算术右移和逻辑右移都可以。实际上,在多数的编译器和及处理器架构的组合中,对有符号数据使用算术右移。
在Java语言中,对两种右移类型有不同的表示,表达式X>>k表示将X算术右移k位,而X>>>k表示将X逻辑右移k位。
注:在IA架构下,左端表示高位,而右端表示低位。
分别写了下面两个C和Java的小程序来看右移运算。
C语言代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
#include <stdio.h> /* * To test shifting for unsigned int and signed int. */ int main(int argc, char *argv[]) { unsigned int a = 0x80000000; int b = 0x80000000; unsigned int c = 0x00000008; int d = 0x00000008; printf("a=%u, hexadecimal format:%x\n", a, a); printf("b=%d, hexadecimal format:%x\n", b, b); printf("a>>2 is %u, hexadecimal format:%x\n", a>>2, a>>2); printf("b>>2 is %d, hexadecimal format:%x\n", b>>2, b>>2); printf("(a>>2) ^ (b>>2) is 0x%x\n", (a>>2)^(b>>2)); printf("c=%u, hexadecimal format:%x\n", c, c); printf("d=%d, hexadecimal format:%x\n", d, d); printf("c>>2 is %u, hexadecimal format:%x\n", c>>2, c>>2); printf("c>>2 is %d, hexadecimal format:%x\n", d>>2, d>>2); printf("(c>>2) ^ (d>>2) is 0x%x\n", (c>>2)^(d>>2)); printf("sizeof(int) = %lu\n", sizeof(int)); } |
运行结果为:
1 2 3 4 5 6 7 8 9 10 11 12 |
master@jay-intel:~/workspace/c-study$ ./shift-test a=2147483648, hexadecimal format:80000000 b=-2147483648, hexadecimal format:80000000 a>>2 is 536870912, hexadecimal format:20000000 b>>2 is -536870912, hexadecimal format:e0000000 (a>>2) ^ (b>>2) is 0xc0000000 c=8, hexadecimal format:8 d=8, hexadecimal format:8 c>>2 is 2, hexadecimal format:2 c>>2 is 2, hexadecimal format:2 (c>>2) ^ (d>>2) is 0x0 sizeof(int) = 4 |
Java程序:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
/** * @className: ShiftTest.java * @author: 笑遍世界 * @description: Java中的算术移位与逻辑移位 * @date 2012-04-19 */ public class ShiftTest { public static void main(String[] args) { int a = 0x80000000; int a1 = a>>2; //算术移位 int a2 = a>>>2; //逻辑移位 System.out.println("a is " + a + "; "+Integer.toBinaryString(a)); System.out.println("a>>2 is " + a1 + "; "+Integer.toBinaryString(a1)); System.out.println("a>>>2 is " + a2 + "; "+Integer.toBinaryString(a2)); System.out.println("integer size is " +Integer.SIZE); } } |
运算结果为:
1 2 3 4 5 |
master@jay-intel:~/workspace/java-study/bin$ java ShiftTest a is -2147483648; 10000000000000000000000000000000 a>>2 is -536870912; 11100000000000000000000000000000 a>>>2 is 536870912; 100000000000000000000000000000 integer size is 32 |
以上代码在Intel平台的Linux环境上运行的。