左移运算符(<<)

左移运算符是用来将一个数的各二进制位左移若干位,移动的位数由右操作数指定(右操作数必须是非负值),其右边空出的位用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

右移运算符(>>)

右移运算符是用来将一个数的各二进制位右移若干位,移动的位数由右操作数指定(右操作数必须是非负值),移到右端的低位被舍弃,对于无符号数,高位补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
学习重点:
  • 左移位运算符和右移位运算符不应用于负数。如果任何一个操作数为负数,则结果为未定义行为。例如, -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)用“符号位”来填充,所以一般用在右移运算中。

发表评论