左移运算符(<<)
左移运算符是用来将一个数的各二进制位左移若干位,移动的位数由右操作数指定(右操作数必须是非负值),其右边空出的位用0填补,高位左移溢出则舍弃该高位。
/* C++程序演示左移运算符的使用 */
#include<stdio.h>
int main()
{
// a = 5(00000101), b = 9(00001001)
unsigned char a = 5, b = 9;
// 结果是 00001010
printf("a<<1 = %d\n", a<<1);
// 结果是 00010010
printf("b<<1 = %d\n", b<<1);
return 0;
}
输出如下:
a<<1 = 10
b<<1 = 18
b<<1 = 18

右移运算符(>>)
右移运算符是用来将一个数的各二进制位右移若干位,移动的位数由右操作数指定(右操作数必须是非负值),移到右端的低位被舍弃,对于无符号数,高位补0。对于有符号数,某些机器将对左边空出的部分用符号位填补(即“算术移位”),而另一些机器则对左边空出的部分用0填补(即“逻辑移位”)。注意:对无符号数,右移时左边高位移入0;对于有符号的值,如果原来符号位为0(该数为正),则左边也是移入0。如果符号位原来为1(即负数),则左边移入0还是1,要取决于所用的计算机系统。有的系统移入0,有的系统移入1。移入0的称为“逻辑移位”,即简单移位;移入1的称为“算术移位”。
/* C++程序演示右移运算符的使用 */
#include <stdio.h>
using namespace std;
int main()
{
// a = 5(00000101), b = 9(00001001)
unsigned char a = 5, b = 9;
// 结果是 00000010
printf("a>>1 = %d\n", a >> 1);
// 结果是 00000100
printf("b>>1 = %d\n", b >> 1);
return 0;
}
输出如下:
a>>1 = 2
b>>1 = 4
b>>1 = 4

学习重点:
- 左移位运算符和右移位运算符不应用于负数。如果任何一个操作数为负数,则结果为未定义行为。例如, -1 << 1 和 1 << -1的结果均未定义。
- 如果数字移位的幅度大于整数的大小,则行为未定义。例如,如果整数使用32位存储,则1 << 33是未定义的。对于较大值的位移,将1ULL<<62,ULL用于unsigned Long,它是用64位定义的,可以存储较大的值。
- 左移1和右移1等于第一项和2与给定元素的幂的乘积(1<<3 = 1*pow(2,3))以及第一项和第二项的除法分别提高到幂2(1>>3 = 1/pow(2,3))。
- 如第1点所述,它仅在数字为正数时起作用。
#include <stdio.h>
int main()
{
int x = 19;
unsigned long long y = 19;
printf("x << 1 = %d\n", x << 1);
printf("x >> 1 = %d\n", x >> 1);
// y左移61位
printf("y << 61 = %lld\n", y << 61);
return 0;
}
输出如下:
x << 1 = 38
x >> 1 = 9
y << 61 = 6917529027641081856
1左移i等于2的i次方。
正如第1点所提到的,它只在数字为正数时有效。
#include<stdio.h>
int main()
{
int i = 3;
printf("pow(2, %d) = %d\n", i, 1 << i);
i = 4;
printf("pow(2, %d) = %d\n", i, 1 << i);
return 0;
}
输出如下:
pow(2, 3) = 8
pow(2, 4) = 16
移位运算包含“逻辑移位”(logical shift)和“算术移位”(arithmetic shift)。
逻辑移位:移出去的位丢弃,空缺位(vacant bit)用 0 填充。
算术移位:移出去的位丢弃,空缺位(vacant bit)用“符号位”来填充,所以一般用在右移运算中。