移位
一、什么是位?
位是用来保存一组项或条件的yes/no信息(有时又称标志)的简洁方法。
二、位操作符
位操作符使用整形的操作数。位操作符将其整形操作数视为二进制位的集合,为每一位提供检验好设置的功能。
对于位操作符,由于系统不能确保如何处理其操作数的符号位,所以强烈建议使用unsigned整形操作数。
1、 & 按位与
两个数据,如果两个相应的二进位都为1,则该位的结果为1,否则为0
作用:
(1)清零、
(2)取一个数中某些指定位
(3)要想将哪一位保留下来,就与一个数进行&运算,此数在该位取1
2、| 按位或
两个数据,如果两个相应的二进位中只要有一个为1,则该位的结果为1,否则为0
作用:
(1)如果想使一个数a的低4位改为1,只需将a与8进制数017(00001111)进行按位或运算即可。
3、^ 异或
若参加运算的两个二进位同号,则结果为0,异号则为1
作用:
(1)使特定位翻转(要使哪几位翻转就将其进行^运算的该几位置为1即可)、
(2)与0^,保留原值、
(3)交换2个值,不用临时变量(a=a^b;b=b^a;a=a^b;)
4、~ 取反
取反即0变1,1变0
5、<< 左移
高位左移后溢出,不起作用,右边补0
左移n位,相当于该数乘以
6、>> 右移
移动到右端低位舍弃,高位补0
右移n位,相当于该数除以
三、下面举个例子:
1、取一个整数a从右端开始的4-7位
步骤:(1)先使a右移4位 a>>4
(2)设置一个低4位全为1,其余全为0的数 ~(~0<<4)
步骤解析: 0: 0000...000000
~0: 1111...111111
~0<<4: 1111...110000
~(~0<<4): 0000...001111
(3)将上面二者进行&运算
a>>4 & ~(~0<<4)
2、在32位的机子上,把一个16进制字符串逆序,例如:"0x12345678"转换成"0x78563412"。
#include <iostream>
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
int ival = 0x12345678;
cout << hex << ival << endl;
int ival2 = (ival>>24) | ((ival>>8) & 0xff00) | ((ival<<8) & 0xff0000) | (ival << 24);
cout << hex << ival2 << endl;
system("pause");
return 0;
}
运行结果:
分析:在32位的机子上,int占4个字节,每个字节是8位。
0x 12 34 56 78
0000 0000 0000 0000 0000 0000 0000 0000
变化后:78 56 34 12
(1)ival>>24 把 ival向右移动24位,舍弃ival后边的24位,由于一个16进制能表示4位,这样就相当于取ival中的12将其放到最低位,即上面78的位置
(2)(ival>>8) & 0xff00 其中ival>>8是把ival向右移动8位,相当于取ival中的123456,将其放到上面的345678位置,再与 0xff00取与运算相当于取123456中的34,将其放到56的位置
(3)同理,(ival<<8) & 0xff0000将取ival 中的56,将其放到34的位置
(ival << 24)将取ival 中的78,将其放到12的位置。
最后在将上面的去或运算:
0x 00 00 00 12
00 00 34 00
00 56 00 00
78 00 00 00
参考资料:《C程序设计》 清华大学出版社 谭浩强 P298-305 《c++ primer 中文版 第四版》 人民邮电出版社 P88-92,P134-136