-
左移
左移,就是把一个数的所有位都向左移动若干位,<<运算符表示
比如
int i =2;
那么二进制为(假设32位系统):0000 0000 0000 0000 0000 0000 0000 0010
i=i<<1;
得到
0000 0000 0000 0000 0000 0000 0000 0100=4
所以说左移1位相当于乘以2,那么左移n位就是乘以2的n次方了(有符号数不完全适用,因为左移有可能导致符号变化,下面解释原因)
1.需要注意的一个问题是int类型最左端的符号位和移位 移出去的情况.我们知道,int是有符号的整形数,最左端的1位是符号位,即0正1负,那么移位的时候就会出现溢出,例如:
int i = 0x40000000; //16进制的40000000,为2进制的01000000...0000
i = i << 1;
那么,i在左移1位之后就会变成0x80000000,也就是2进制的100000...0000,符号位被置1,其他位全是0,变成了int类型所能表示的最小值,32位的int这个值是-2147483648,溢出
2.左移里一个比较特殊的情况是当左移的位数超过该数值类型的最大位数时,编译器会用左移的位数去模类型的最大位数,然后按余数进行移位,如:
int i = 1, j = 0x80000000; //设int为32位
i = i << 33; // 33 % 32 = 1 左移1位,i变成2
j = j << 33; // 33 % 32 = 1 左移1位,j变成0,最高位被丢弃
总结:左移就是: 丢弃最高位,0补最低位
-
右移
右移的概念和左移相反,就是往右边挪动若干位,运算符是>>
右移对符号位的处理和左移不同,对于有符号整数来说,比如int类型,右移会保持符号位不变,例如:
int a =0x80000000;
二进制为:1000 0000 0000 0000 0000 0000 0000 0000
右移一位:11000 0000 0000 0000 0000 0000 0000 0000 =0xc0000000;
就是说,符号位向右移动后,正数的话补0,负数补1,也就是汇编语言中的算术右移.同样当移动的位数超过类型的长度时,会取余数,然后移动余数个位.
负数10100110 >>5(假设字长为8位),则得到的是 11111101
总之,在C中,左移是逻辑/算术左移(两者完全相同),右移是算术右移,会保持符号位不变.实际应用中可以根据情况用左/右移做快速的乘/除运算,这样会比循环效率高很多.