位运算符
一、位运算符
位运算符:用来操作二进制位(bit)
注意:位运算符的运算过程都是基于二进制的补码运算
运算符 | 描述 | 运算规则 |
---|---|---|
<< | 二进制左移 | 将一个数的各二进制位全部左移指定的位数,左边的二进制位丢弃,右边补0。 |
>> | 二进制右移 | 将一个数的各二进制位全部右移指定的位数,正数左补0,负数左补1,右边丢弃。 |
& | 按位与 | 两个二进制位都为 1,结果为1,否则为0。 |
| | 按位或 | 两个二进制位只要有一个为1(包含两个都为 1 的情况),结果为1,否则为0。 |
^ | 按位异或 | 两个二进制位一个为0,一个为1,结果为1,否则为0。 |
~ | 按位取反 | 将每一个二进制位(包括符号位)变成相反值,即 0 变成 1 , 1 变成 0 。 |
结合赋值运算符的经验,这里有:<<= 、 >>= 、 &= 、 ^= 等
二、左移:<<
1.运算规则
运算规则:在一定范围内,数据每向左移动一位,相当于原数据 * 2。(正数、负数都适用),效率比使用
*
高
【注意】当左移的位数n超过该数据类型的总位数时,相当于左移(n-总位数)位
2.实例
3<<4
类似于 3 ∗ 2 4 3 * 2^4 3∗24 => 3 * 16 => 48
-3<<4
类似于 − 3 ∗ 2 4 -3 * 2^4 −3∗24 => -3*16 => -48
3.练习
高效的方式计算2 * 8的值
答案:2 << 3 、 8 << 1 // 这两个就不比效率了,都同时常数级别的
三、右移:>>
1.运算规则
运算规则:在一定范围内,数据每向右移动一位,相当于原数据 / 2。(正数、负数都适用),效率比使用
/
高
【注意】
- 如果不能整除,
向下取整
。- 右移运算符最好只用于无符号整数,不要用于负数。因为不同系统对于右移后如何处理负数的符号位,有不同的做法,可能会得到不一样的结果。
2.实例
69>>4
类似于 69 / 2 4 69 / 2^4 69/24 => 69 / 16 => 4
-69>>4
类似于 − 69 / 2 4 -69 / 2^4 −69/24 => -69 / 16 => 4
四、按位与:&
1.运算规则
运算规则:对应位都是1才为1,否则为0。
- 1 & 1 结果为1
- 1 & 0 结果为0
- 0 & 1 结果为0
- 0 & 0 结果为0
2.实例
9 & 7 = 1
-9 & 7 = 7
五、按位或:|
1.运算规则
运算规则:对应位只要有1即为1,否则为0。
- 1 | 1 结果为1
- 1 | 0 结果为1
- 0 | 1 结果为1
- 0 & 0 结果为0
2.实例
9 | 7 = 15
-9 | 7 = -9
六、按位异或:^
1.运算规则
运算规则:对应位一个为1一个为0,才为1,否则为0。
- 1 ^ 1 结果为0
- 1 ^ 0 结果为1
- 0 ^ 1 结果为1
- 0 ^ 0 结果为0
2.实例
9 ^ 7 = 14
-9 ^ 7 = -16
七、按位取反:~
1.运算规则
运算规则:对应位为1,则结果为0;对应位为0,则结果为1。
- ~0就是1
- ~1就是0
2.实例
~9 = -10
Tips:-10 取反就是 9
~-9 = -8
八、应用
大家肯定和我一样,心里一万个为什么,学这个有啥用啊???确实,我们平常写代码时几乎不会使用,但是 C语言 的源码中会用到,为了追求更高的性能。例如下面几个场景:
1.特定位清零
待清零的位与0,其它位与1
示例:设字符型 x 的当前值为 53,将其最低两位清 0,其余位保持不变
int main() {
char x = 53; // 0b00110101
x = x & 252; // 0b11111100
printf("%d", x); //0b00110100
return 0;
}
2.判断特定位是否为零
待判定位与 1,其它位与 0;判与运算结果是否为 0
示例:设字符型 x 的当前值为 53,判定其最高位是否为 0
int main() {
char x = 53; // 0b00110101
x = x & 128; // 0b10000000
if(x == 0)
printf("最高位为0");
else
printf("最高位不为0");
return 0;
}
3.保留特定位
待保留位全部与 1,其余位与 0
示例:设字符型 x 的当前值为 53,保留其最低 4 位,其余位清零
int main() {
char x = 53; // 0b00110101
x = x & 15; // 0b00001111
printf("%d\n",x); //0b00000101
return 0;
}
4.特定位置为1,其余为不变
待置为1的位或1,其它位或0
示例:设字符型 x 的当前值为 53,将其最低两位置 1,其余位保持不变
int main() {
char x = 53; // 0b00110101
x = x | 3; // 0b00000011
printf("%d\n",x); //0b00110111
return 0;
}
5.特定位取反
待取反位异或 1,保持位异或 0
示例:设字符型 x 的当前值为 53,将其最低两位取反,其余位保持不变
int main() {
char x = 53; // 0b00110101
x = x ^ 3; // 0b00000011
printf("%d\n",x); //0b00110110
return 0;
}