位操作
C语言中,可以单独操控变量中的位.
位运算符
二进制反码或按位取反: ~
~(00000010) //表达式
(11111101) //结果值
按位与: &
与运算同1为1,其余为0
(00000010)&(00000001) //表达式
(00000000) //结果值
按位或: |
或运算同0为0,其余为1
(00000010)|(00000001) //表达式
(00000011) //结果值
按位异或: ^
异或运算不同为1,相同为0
(00000010)^(00000001) //表达式
(00000011) //结果值
为运算符的用法
按位与运算符 &
常用于掩码.
(00000011) & (00000001)
(00000001) //0掩码
按位或运算符 |
常用于打开位.
(00000001) | (00000010)
(00000011) //1开位
按位运算符 & ~
用于关闭位
(00000011) & ~(00000001)
(00000010) //1关位
按位运算符 ^
用于切换位
(01010101) ^ (00001111)
(01011001) //0不变1切换
检查位的值
//检查flags中1号位是否为1.
flags = (10101010);
mask = (00000010);
if((flags & mask) == mask)
cout<<"flags中1号位是1"<<endl;
移位运算符
左移<<
移除左末端位,用0填充
(00000010) << 2
(00001000)
右移>>
移除右末端位,无符号填0,有符号取决于机器
移位运算符的用法
移位运算符针对2的幂提供快速有效的乘法和除法.类似于十进制中移动小数点来乘以或除以10
num << n; //num乘以2的n次幂
num >> n; //如果num非负,则num除以2的n次幂
位域
操控位的第二种方法是位域(位字段)
位域是一种数据结构,可以把数据以位的形式储存.位域的存储顺序与机器有关.其类型必须是整型或枚举类型,且引用与指针无法作用于位域
//创建两个2位字段和一个8位字段
struct bit
{
unsigned int code1 : 2;
unsigned int code2 : 2;
unsigned int code3 : 8;
} proced;
//赋值,不可超出字段的可容纳范围[2,2^n]
proced.code1 = 0;
proced.code2 = 3;
proced.code3 = 102;
若声明的总位数超过一个unsigned int 类型,会用到下一个unsigned int类型的存储位置.但一个字段不允许跨越两个unsigned int之间的边界.编译器会自动移动跨界的字段,保持unsigned int的边界对齐.一旦发生这种情况,第一个unsigned int中会留下一个未命名的"洞".
在x86系统中,unsigned int为32位.
可以用未命名的字段"填充"未命名的"洞".
struct stuff
{
unsigned int field1 : 30;
unsigned int : 2;
unsigned int field2 : 4;
unsigned int : 0;
unsigned int field3 : 4;
};
//field1于field2之间有一个2位的空隙填充洞
//field3则会存储在下一个unsigned int中