移位操作符的操作数只能是整数。
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。入下图所示。