详解C++中的移位运算

移位运算:

  • 逻辑移位

逻辑移位是指逻辑左移和逻辑右移,移出的空位都用0来补。

  • 算术移位

算术移位 就需要分有符号型值和无符号型值

  1. 对于无符号型值,算术移位等同于逻辑移位。 
  2. 而对于有符号型值 ,算术左移等同于逻辑左移,算术右移补的是符号位,正数补0,负数补1

其中,第2点涉及到负数在计算机中的存储方式:

首先复习一下原码、反码、补码

有符号型值分为正数和负数(包括正浮点数,和负浮点数),规定最高位为符号位,正数为0,负数为1。

原码:10进制转换成2进制是原码,只不过正数的原码是本身符号位为0,负数的原码符号位为1(1的原码是0000 0001,-1的原码是1000 0001)。

反码: 正数的反码是本身,负数的反码是负数的原码非符号位0变为1,1变为0(-1的原码是1000 0001   它的反码就是 1111 1110)。

补码: 正数的补码是本身,负数的补码就是负数的反码加1(-1的原码是1000 0001,它的反码就是 1111 1110  它的补码就是 1111 1111)。

总结:正数的原码,反码 ,补码三值合一, 负数的原码,反码,补码不同。事实证明,计算机中负数是以补码存储的,也可以推广到——计算机中所有数都是以补码形式存储的

!!!补码求原码的过程,依然是(1)符号位不变,其它位取反;(2)符号位不参与计算,其余加1。

详见原文:负数在计算机中的存储问题

因此,负数的算术右移,实际上是对补码的右移。比如:

char i=-8;//原码为1000 1000,反码为1111 0111,补码为1111 1110;
i>>=3;    //右移3位,即补码右移3位,变成:
          //补码为1111 1111,取反为10000 0000,加1为1000 0001,为-1;

VS系列的编译器中,对无符号型值进行移位时,默认是逻辑左移和逻辑右移;

而对于有符号型值进行移位时,左移还是逻辑左移,但右移时执行的是算术右移

猜你喜欢

转载自blog.csdn.net/Beast_Liu/article/details/85268495