1、位与&
1)“位与”:& “逻辑与”:&&
2) 真值表:1&0 = 0 、0&1 = 0、0&0 = 0、1&1 = 1 只有当1与1位与时才是1,其他的值相与都是0
3)“位与”就是把2个十六进制的数先分别转换为二进制,然后再相与。“逻辑与”就是把2个十六进制分别看成2个整体,2个整体相与。
例子:0xA & 0xB = 0xA //位与 0xA && 0xB = 1 //逻辑与
0xA:1 0 1 0 0xA = 1 (ture)
0xB:1 0 1 1 0xB = 1 (ture)
位与: 1 0 1 0 逻辑与 : 1
2、位或|
1)“位或”:| “逻辑或”:||
2) 真值表:1|0 = 1 、0|1 = 1、0|0 = 0、1|1 = 1 只有两个0位或的时候才是0,其余的都是1
3) “位或”就是把2个十六进制的数先分别转换为二进制,然后再位或;“逻辑或”就是把2个十六进制分别看成2个整体,2个整体位或。
例子:0xA | 0xB = 0xB 0xA || 0xB = 1
0xA:1 0 1 0 0xA = 1 (ture)
0xB:1 0 1 1 0xB = 1 (ture)
位或: 1 0 1 1 逻辑或 : 1
3、位取反 ~
1)“位取反”:~ “逻辑取反”:!
2)“位取反”就是把十六进制数先转换为二进制,然后把每一位取反(1取反就变为0,0取反就为1);“逻辑取反”就是把十六进制数看成一个整体,然后取反(非0的数都是为真,逻辑取反后为假;0逻辑取反为真)。
3) 例子:0xA = 1 0 1 0 0xA (非0为真(即1))
~0xA = 0 1 0 1 = 0x5 !0xA = 0
~~0xA = 1 0 1 0 = 0xA !!0xA = 1
4、位异或 ^
1) “位异或”: ^
2) 真值表:1^0=1 0^1=1 0^0=0 1^1=0 两个数相等则为0,不相等则为1
3) 例子: 66 ^ 33 = 99
66: 1 0 0 0 0 1 0
33: 0 1 0 0 0 0 1
99: 1 1 0 0 0 1 1
代码: unsigned int a = 66, b = 33;
unsigned int c = a^b;
printf("c = %d ", c);
5、左移位<< 右移位>>
无符号数,左移时在右边补0,右移时在左边补0
二.位操作的实际应用
一般在操作寄存器的时候使用,如32位的arm寄存器,每个位代表的pin脚不同,效果也不同。有时候你只想改变某个pin脚的值从而实现某项功能,其余pin脚保持不变,就得使用位操作,只对目标位进行操作。操作的方式是:读->改->写。不要直接给寄存器赋目标值是因为你只知道要把目标位设置为某值,但是其他的位你并不知道原本是多少,所以要先读取这个寄存器的整体值,然后再修改其中的目标位,然后再把修改后的值写到寄存器。
1)特定位清零用&
譬如:将0xAAAAAAAA 的bit8 ~bit15清零,其他位保持不变。
分析:[位与]任何数(0/1)与1位与时为本身,与0位与为0,所以可以用位与的方式。
unsigned int a = 0xAAAAAAAA;
unsigned int b = 0xFFFF00FF;
unsigned int c;
c = a & b;
printf("c = 0x%x ", c); //c = 0xaaaa00aa
2)特定位 置1用 |
譬如:将0xffff00ff的bit8 ~bit15置1,其他位保持不变。
分析:位或 任何数(0/1)与1位或变为1,与0位或为本身
unsigned int a = 0xffff00ff;
unsigned int b = 0x000ff00;
unsigned int c;
c = a | b;
printf("c = 0x%x ", c); // = 0xffffffff
3)特定位取反用 ^
譬如:将0xffff00ff的bit8 ~bit15取反,其余保持不变
分析:位异或 任何数(0/1)与1位异或会取反,与0位异或为本身
unsigned int a = 0xffff00ff;
unsigned int b = 0xff00;
unsigned int c;
c = a ^ b;
printf("c = 0x%x ", c); // = 0xffffffff
三、特定二进制数的获取
由于上面示例中的unsigned int b的值太过于呆板,后续看代码的时候可能不知道为什么是这个值,所以需要以另外的方式来表达(主要是通过位移和位取反来获取这个特定的二进制数)。
(1) 譬如:unsigned int b = 0xff00; 中的0xff00
可表示为:0xFF<<8 (0xFF :8个二进制1 <<: 左移 8: 8位)
(2) 需要一个bit3 ~bit7,bit23~bit25为1的数(隐含意思是其他位都为0)
可为:0x1F<<3 | 0x7<<23
1F (7-3+1=5个1,转换为十六进制则为1F);
7 ( 25-23+1=3个1,转换为十六进制则为7)
| ( 位或,任何数与1位或都为1,与0位或为本身,所以这里用位或就相当于把这2个位移后的数叠加起来)
(3) 需要一个bit3 ~ bit7为0的数
可为:~(0x1F<<3)
总结:当需要的1比较少,需要的0比较多,就使用1位移的方式;当需要的0比较少,需要的1比较多,就使用位移然后取反的方式;当需要的数比较复杂,如bit3 ~bit7,bit23~bit25为1,就可以先位移然后位或的方式。