按位运算符
基本位运算符:取反~, 与&, 或|, 异或^
- 按位取反: ~
unsigned char tmp = 2;
printf("%d", ~tmp);
2的二进制是:0000 0010
取反后:1111 1101 解释成补码为:(等价于原码1000 0011 = -3)
- 按位与:&
只有1 & 1 = 1, 其他都为0 , 即:全1为1,有0则0
- 按位或:|
只有0 | 0 = 0, 其他都为1,即:全0为0,有1则1
- 按位异或: ^
相同为0, 相异为1
0 ^ 0 = 0,1 ^ 1 = 0
0 ^ 1 = 1, 1 ^ 0 = 1
基本运算符的应用
&
的应用:掩码MASK
不论是0还是1,和0进行与运算为0,和1进行与运算不变:
因此与
上MASK后,0对应的位被消去,只有1对应的位保留:类似于用0掩盖住原二进制串上对应的位:结果是只有1对应的位被保留,其余的位为0;
- 可简写为:
a &= MASK;
- 检查位
目的:检查MASK中1对应位是否为1
先用掩码(与上MASK),得到第一次处理后的二进制串(其余不相干的位置为0),然后==判断是否与MASK相等:若相等说明MASK中1对应的位也都是1,否则有的位检查失败
return (a & MASK) == MASK ? true : false;
- 关闭位(清空位)
类似于掩码:用&将0对应位清空(置为0),一般先将MASK取反,MASK中1的位就是要关闭的位
a &= ~MASK;
|
的应用:打开位(设置位)
无论0还是1,和1进行或运算为1:
因此或
上MASK后,可将特定位置为1(ON),用于对特定硬件发送打开命令
a |= MASK;
^
的应用:切换位
无论0还是1,与0异或不变,与1异或“翻转”:
因此异或
上MASK后,可将MASK中1对应的位翻转
a ^= MASK;
移位运算符: 右移 >>, 左移 <<
- 左移
<<
: 低位补0
a << n //a左移n位
- 右移
>>
:无符号数补0,有符号数看机器
a >> n; //a右移n位
移位运算符的应用:
a << n; // 左移一位相当于*2: 左移n位相当于*2^n
a >> n; // 如果a非负,右移一位相当于/2:右移n位相当于/2^n
可以利用移位+掩码:来提取某个或某些位
应用:ItoB(),invert_end()
获得int 的二进制:并实现将低n位翻转的函数
#include <stdio.h>
#include <limits.h> //提供CHAR_BIT:本机一个字节的位数(通常为8)
#define MASK 0x01
void ItoB(int, char*);
void ShowBit(char*);
int invert_end(int, int);
int main(){
char ans[CHAR_BIT * sizeof(int) + 1];
int in;
puts("Enter integers and see them in binary.(Non-numeric to quit)");
while(scanf("%d", &in) == 1){
ItoB(in, ans);
printf("%d in binary is ", in);
ShowBit(ans);
putchar('\n');
puts("Inverting the last 4 bits.");
ItoB(invert_end(in, 4), ans);
ShowBit(ans);
putchar('\n');
}
return 0;
}
void ItoB(int n, char* s){
int i;
const static int size = CHAR_BIT * sizeof(int);
for(i = size - 1; i >= 0; --i, n >>= 1){
s[i] = (n & MASK) + '0';
}
s[size] = '\0';
return s;
}
void ShowBit(char* s){
int i = 0;
while(s[i]){
putchar(s[i]);
if(++i % 4 == 0 && s[i]){
putchar(' ');
}
}
}
int invert_end(int n, int bits){
int mask = 0;
int bitval = 1;
while(bits-- > 0){
mask |= bitval;
bitval <<= 1;
}
return n ^ mask;
}
- 输出:
- 实现翻转低位功能后: