位运算之左移(<< )
位运算之左移(<< )
位运算中的左移操作符(<<)是编程中一个基础且重要的概念。本文将从正整数和负整数的左移运算规则开始讲解,详细解释左移操作的原理,并通过补码的概念进一步说明负数左移的机制。此外,文章还讨论了左移运算中的溢出情况,特别是当左移位数大于或等于32位时的处理方式。
1.<< 左移操作符
1.1 正整数左移运算
正整数左移操作符的移位规则:左边抛弃、右边补0。左移一位右边添加一个0,结果就是乘以2;左移两位,右边添加2个0,结果就是乘以2^2;左移n位,右边添加n个0,结果就是乘以2^n;在进行左移运算时,要注意溢出的情况。
1.2 负整数左移运算
(-x)<<y <=>-(x<<y)
:即对负数左移y位等价于对正数左移y位后再取负。我们通过值的角度理解就非常合理。
也可以用
补码
来解释:
-(7<<1):
7的补码是:00000000 00000000 00000000 00000111,
7的补码左移1位:00000000 00000000 00000000 00001110,结果为14,再取负为-14。
-7<<1:
-7的补码是:11111111 11111111 11111111 11111001,
-7的补码左移1位:11111111 11111111 11111111 11110010,原码为:10000000 00000000 00000000 00001110,结果为-14。
1.3 左移时溢出
1.3.1 左移的位数大于或者等于32位
如上面的代码所示,9二进制表达为:00000000 00000000 00000000 00001001;
1.从移位的角度来看溢出:
第一步,左移32位:00000000 00000000 00000000 00000000(正)
第二步,求出其原码:11111111 11111111 11111111 11111111+1=00000000 00000000 00000000 00000000;此时,结果为0,但是VS下的结果为9;why?
这是因为C语言会将超出的位数进行取模操作,即将移位的位数对操作数的位数取模,然后进行相应的位移。即9左移32位,则先将32对9的位数32进行取模运算,然后进行相应的左移运算。因为如果直接移位的话,当移位长度大于31时必定是0;从而原式的值等于00000000 00000000 00000000 00001001左移0位,也就是9本身。
2.从值的角度来看溢出
int类型的9左移28位和31位的结果如下:
int类型的9的原码、反码、补码是:00000000 00000000 00000000 00001001,左移28位后的补码为:10010000 00000000 00000000 00000000,则原码为11110000 00000000 00000000 00000000,即为:-1879048192;
左移31后的补码为:10000000 00000000 00000000 00000000,则原码为:10000000 00000000 00000000 00000000,对于这个二进制序列,int类型去解析这个数据的话,是规定好的,就是int的最小值-2147483648。入下图所示。