C语言 移位操作符

一、介绍

关于移位操作符,我们分为两类,一个是左移操作符<<  , 一个是右移操作符>>

且两位操作符都与二进制的补码息息相关。

补码详细请看http://t.csdn.cn/9W84t

警告:对于移位运算符,不要移动负数位,这个是标准未定义的。 

二、<< 左移操作符

左移操作符: 左边丢弃,右边补0

例如:

int a = 7

// 0000 0000 0000 0000 0000 0000 0000 0111  - 7的原码,也是7的补码

a = a << 1  

//将7的补码向左移动一位,随后在右边补上一个数字0 
//因为int的内存之中只能存放32位bit,所以从左往右数32位数留下,多出的数字剔除
//而在此运算中,最左边移动的哪一位数字,就是被剔除的
  
向左移动的一位
   ↓
// 0 0000 0000 0000 0000 0000 0000 0000 1110
                                           ↑
                                          向右补上的数字0

// 0000 0000 0000 0000 0000 0000 0000 1110
 
//因为是正数,补码原码是一致的,所以可以直接进行计算,最后得出的结果是14

当然,以上是针对与正数的操作,而对于负数也是同样的道理,不过负数要先变成补码的形式,随后在进行移位操作。

int b = -7

// 1000 0000 0000 0000 0000 0000 0000 0111 - -7的原码

// 1111 1111 1111 1111 1111 1111 1111 1000 - -7的反码

// 1111 1111 1111 1111 1111 1111 1111 1001 - -7的补码

b = b << 1 

//进行左边移动一位,右边补上一位数字0

 左边移动一位
   ↓
// 1111 1111 1111 1111 1111 1111 1111 1001 
                                          ↑
                                          右边需要补上一位数字0
 左边移动一位
   ↓
// 1 1111 1111 1111 1111 1111 1111 1111 0010
                                           ↑
                                          右边补上一位数字0

//整理得到:

// 1111 1111 1111 1111 1111 1111 1111 0010 

最后得到结果,需要变回原码 

// 1000 0000 0000 0000 0000 0000 0000 1101 -  -7 << 1 的反码

// 1000 0000 0000 0000 0000 0000 0000 1110 -  -7 << 1 的原码

最后经过计算得知 -7<<1 的结果是 -14 

通过以上结果,我们得知左移操作符<<具有乘2的效果。

 7 << 1  = 14
 7 << 2  = 28
 7 << 3  = 56
 7 << 4  = 112

-7 << 1  = -14
-7 << 2  = -28
-7 << 3  = -56
-7 << 4  = -112

从而得出结论:
a<<1       a×2
a<<2      a×2×2
a<<3      a×2×2×2

三、右移操作符 >>

右移操作符分为逻辑右移算术右移

1、逻辑右移

逻辑右移:左边用0填充,右边丢弃

例如:

int a = -1 

// 1111 1111 1111 1111 1111 1111 1111 1111  - -1的补码

a >> 1 

左边补一个数字0
   ↓
// 01111 1111 1111 1111 1111 1111 1111 1111
                                          ↑
                                        右边丢弃一位
左边补一个数字0
   ↓
// 0111 1111 1111 1111 1111 1111 1111 1111  - -1 >> 1 的结果
                                          ↑
                                        右边丢弃一位

逻辑右移有一个弊端,如上所示,若是一个负数需要进行右移时,使用了逻辑右移,那么这个负数会变成正数。

也因此,绝大多数的编译器并不采用逻辑右移,反而采用算术右移。

2、算术右移

算术右移:右边丢弃,若是负数左边补充1,若是正数左边补充0

例如:

int b = -1 

// 1111 1111 1111 1111 1111 1111 1111 1111  - -1的补码

b >> 1 

左边补一个数字1
   ↓
// 11111 1111 1111 1111 1111 1111 1111 1111
                                          ↑
                                        右边丢弃一位
左边补一个数字1
   ↓
// 1111 1111 1111 1111 1111 1111 1111 1111  - -1 >> 1 的结果
                                          ↑
                                        右边丢弃一位

三、注意事项

移位操作符的操作数只能是整数。

float f = 4.5f

猜你喜欢

转载自blog.csdn.net/2301_76445610/article/details/132121579