位移位运算符
位移位运算符是将数据看成二进制数,对其进行向左或向右移动若干位的运算。位移位运算符分
为左移和右移两种,均为双目运算符。第一运算对象是移位对象,第二个运算对象是所移的二进制位
数
。
移位时,移出的位数全部丢弃,移出的空位补入的数与左移还是右移花接木有关。如果是左移,
则规定补入的数全部是 0;如果是右移,还与被移位的数据是否带符号有关。若是不带符号数,则补
入的数全部为 0;若是带符号数,则补入的数全部等于原数的最左端位上的原数(即原符号位)。具体移
位
规
则
如
下
所
示
。
位
移
位
运
算
符
的
优
先
级
如
下
:
·
算 术 运 算 符 优 先 于 位 移 位 运 算 符
优 先 于
关 系 运 算 符
· 位 移 位 运 算 符 是 同 级 别 的 , 结 合 性 是 自 左 向 右
例 如 , 设 无 符 号 短 整 型 变 量 a 为 0111( 对 应 二 进 制 数 为 0000000001001001),
则 : a<<3 结 果 为 01110( 对 应 二 进 制 数 为 0000001001001000) , a 不 变
a>>4 结 果 为 04 ( 对 应 二 进 制 数 为 0000000000000100) , a 不 变
又 如 , 设 短 整 型 变 量 a 为 -4( 对 应 二 进 制 数 为 1111111111111100),
则 : a<<3 结 果 为 -32( 对 应 二 进 制 数 为 1111111111100000) , a 不 变
a>>4 结果为-1(对应二进制数为 1111111111111111),a 不变
C 语言里的左移和右移运算
先说左移,左移就是把一个数的所有位都向左移动若干位,在 C 中用<<运算符.例如:
int
i
=
1;
i = i << 2; //把 i 里的值左移 2 位
也就是说,1 的 2 进制是 000...0001(这里 1 前面 0 的个数和 int 的位数有关,32 位机器,gcc 里有 31
个 0),左移 2 位之后变成 000... 0100,也就是 10 进制的 4,所以说左移 1 位相当于乘以 2,那么左移 n
位就是乘以 2 的 n 次方了(有符号数不完全适用,因为左移有可能导致符号变化,下面解释原因)
需要注意的一个问题是 int 类型最左端的符号位和移位移出去的情况.我们知道,int 是有符号的整形数,
最左端的 1 位是符号位,即 0 正 1 负,那么移位的时候就会出现溢出,例如:
int i = 0x40000000; //16 进 制 的 40000000, 为 2 进 制 的 01000000...0000
i = i << 1;
那么,i 在左移 1 位之后就会变成 0x80000000,也就是 2 进制的 100000...0000,符号位被置 1,其他
位全是 0,变成了 int 类型所能表示的最小值,32 位的 int 这个值是-2147483648,溢出.如果再接着把 i
左移 1 位会出现什么情况呢?在 C 语言中采用了丢弃最高位的处理方法,丢弃了 1 之后,i 的值变成了 0.
左移里一个比较特殊的情况是当左移的位数超过该数值类型的最大位数时,编译器会用左移的位数去
模类型的最大位数,然后按余数进行移位,如:
int i = 1, j = 0x80000000; //
设
int
为
32
位
i = i << 33;
// 33 % 32 = 1
左
移
1
位
,i
变
成
2
j = j << 33; // 33 % 32 = 1 左移 1 位,j 变成 0,最高位被丢弃
在用 gcc 编译这段程序的时候编译器会给出一个 warning,说左移位数>=类型长度.那么实际上 i,j 移
动的就是 1 位,也就是 33%32 后的余数.在 gcc 下是这个规则,别的编译器是不是都一样现在还不清楚.
总之左移就是: 丢弃最高位,0 补最低位
再说右移,明白了左移的道理,那么右移就比较好理解了.