title | date | tags | categories | description | |||
---|---|---|---|---|---|---|---|
C语言位运算符及其使用
|
2020-04-23 03:01:19 -0700
|
|
|
|
按位逻辑运算符
符号
运算符 | 含义 |
---|---|
~ | 按位取反 |
& | 按位与 |
` | ` |
^ | 按位异或 |
用法
掩码
所谓掩码就是一些设置为开(1)或关(0)的位组合 例如
#include <stdio.h>
#define MASK 0x02
int main(void) {
int a = 0b11111111;
printf("%d\n", a);
a &= MASK;
printf("%d\n", a);
}
输出
255
2
按位与,二者都为1,结果才为1 0x02=0b00000010 所以除了第二位保持不变,其他位都被置0
常用于
ch &= 0xff;
这个掩码保持ch后8位不变,其他位都设为0,无论ch原来是8,16,32位,最终的值都被修改为一个8位字节
打开位
有时需要打开某一位而保持其他位不变,则可以利用|
进行或运算
//假设 flags 为 0b01001100
//假设 MASK 为 0b00000001
flags |= MASK;
//经过或运算,flags 变为 0b01001101
其他位不变而把最低位打开了
关闭位
flags &= ~MASK;
切换位
使用^
运算符,首先对于异或运算有一个特点 0^b=b 1^b=~b 即一个数与0异或该位保持不变,而如果与1异或则会被取反
//假设 flags 为 0b00001111
//假设 MASK 为 0b10110110
flags ^= MASK;
结果flags将会变为0b10111001,即flags中与MASK为1的位相对应的位都被切换了,为0的都保持不变
检测位的值
比如检测flags中第一位的值是否为1,则flags等于0bxxxxxxxx,这些位都不确定,所以不能使用
//MASK==0x00000001
if(flags == MASK)
printf("yes");
而应当
if((flags & MASK) == MASK)
printf("yes");
由于&比==优先级低,所以要加上括号
移位运算符
符号
左移运算符<<
将左侧运算对象的每一位向左移动右侧对象的位数,左末端值丢失,用0填充空出的位置 右移运算符>>
将右侧运算对象的每一位向右移动右侧对象的位数,右末端值丢失,对于无符号类型,用0填充空出的位置,对于有符号类型,结果取决于机器,可用0或符号位的副本填充
用法
乘除法
- 移位运算符可以提供快速有效的针对2的幂的乘除法
num <<= n; //num乘以2的n次幂
num >>= n; //如果num非负(因为不同机器右移结果不确定),则用num除以2的n次幂
提取位
假设用一个unsigned long
类型的值表示颜色,低阶位字节存储红色的强度,下一字节为绿色,再下一字节为蓝色,随后你希望将每种颜色的强度存储在3个不同的unsigned char
中,如下
#include <stdio.h>
#define BYTE_MASK 0xff
unsigned long color;
unsigned char red, green, blue;
int main(void) {
color = 0x1f7bea;
red = color & BYTE_MASK;
green = (color >> 8) & BYTE_MASK;
blue = (color >> 16) & BYTE_MASK;
printf("color=%lx\nblue=%x,green=%x,red=%x", color, blue, green, red);
}