C语言中,位操作一共有6个位操作符,分别是位与&(AND),位或|(OR),位取反~(一元运算符),位异或^(XOR),左移位<<,右移位>>。
2.1.1位与&
(1)位与操作符&,逻辑与操作符&&,两者不同。位与是按位进行与操作,只有0或者1这两个操作数;逻辑与操作数是只要不是0的,都为1,逻辑与是两个操作数作为整体来相与的。
(2)真值表:
操作数A | 操作数B | A&B |
0 | 0 | 0 |
0 | 1 | 0 |
1 | 0 | 0 |
1 | 1 | 1 |
(3)规律总结:遇0为0,遇1不变。
(4)举例:两个操作数A:0x12356705,B:0xAAAABBCC,A&B?A&&B?
A:0x12356705=10010001101010110011100000101;
B:0xAAAABBCC=10101010101010101011101111001100
00010010001101010110011100000101
& 10101010101010101011101111001100
00000010001000000010001100000100
故A&B=00000010001000000010001100000100
A&&B=0x12356705&&0xAAAABBCC=1&&1=1。
2.1.2位或|
(1)位或操作符只有一个|,即操作符为|;逻辑或操作符有两个|,即操作符为||。位或是按位进行或操作,只有0或者1这两个操作数;逻辑或操作数是只要不是0的,都为1。
(2)真值表
操作数A | 操作数B | A|B |
0 | 0 | 0 |
0 | 1 | 1 |
1 | 0 | 1 |
1 | 1 | 1 |
(3)规律总结:遇0不变,遇1为1。
(4)举例:两个操作数,A:0x12345678,B:0x15141251;A|B?A||B?
A:0x12345678=10010001101000101011001111000
B:0x15141251=10101000101000001001001010001
10010001101000101011001111000
|10101000101000001001001010001
10111001101000101011001111001
故A|B=10111001101000101011001111001;
而A||B=0x12345678||0x15141251=1||1=1。
2.1.3位取反~(一元运算符)
(1)按位取反操作符为~,逻辑取反操作符为!。按位取反是按位逐位取反,即0按位取反变成1,1按位取反变成0。而逻辑取反则只要不是0的按逻辑取反都变成0,而0按逻辑取反变成1。
(2)真值表
操作数A | ~A |
0 | 1 |
1 | 0 |
(3)举例:操作数A:0x12579233,~A?,!A?,~~A?,!!A?
A=0x12579233=00010010010101111001001000110011
故:~ A=11101101101010000110110111001100
!A=!1=0
~~A=00010010010101111001001000110011=A
!!A=!0=1≠A
由以上有趣现象,我们可以总结为:任何非0的数被按逻辑取反再取反就会得到1;任何非0的数倍按位取反再取反就会得到他自己。
2.1.4位异或^
(1)位异或的操作符为^。
(2)真值表
操作数A | 操作数B | A^B |
0 | 0 | 0 |
0 | 1 | 1 |
1 | 0 | 1 |
1 | 1 | 0 |
(3)规律总结:遇0不变,遇1相反。记忆:异或就是当两个操作数相异时进行或操作。
(4)举例:两个操作数A:0x12345665,B:0x55662331,A^B?
A=0x12345665=00010010001101000101011001100101
B=0x55662331=01010101011001100010001100110001
00010010001101000101011001100101
^01010101011001100010001100110001
01000111010100100111010101010100
故A^B=01000111010100100111010101010100。
位与、位或、位异或的特点总结:
位与:(任何数,其实就是1或者0)与1位与无变化,与0位与变成0
位或:(任何数,其实就是1或者0)与1位或变成1,与0位或无变化
位异或:(任何数,其实就是1或者0)与1位异或会取反,与0位异或无变化
2.1.5左移位<<与右移位
在C语言中,移位操作要取决于数据结构。
(1) 在无符号数中,左移时右侧补0(相当于逻辑移位)。
(2) 在无符号数中,右移时左侧补0(相当于逻辑移位)。
(3) 在有符号数中,左移时右侧补零(叫算术移位,相当于逻辑移位)。
(4) 在有符号数中,右移时左侧补符号位(如果正数就补0,负数就补1,叫做算术移位)。
嵌入式中研究的移位,我们使用的移位都是无符号数!