C语言位运算
前言
- 要学习位运算,首先要知道源码、反码、补码。
- 整数在底层使用补码的二进制存储,正数的源码、反码、补码相同。
- 有符号数的二进制第一位是符号位,0代表正数、1代表负数。
- 负数的反码是源码的符号位不变,其他位取反(0变1,1变0)。
- 负数的补码是反码加一。
int num1 = 10;
00000000 00000000 00000000 00001010 源码
00000000 00000000 00000000 00001010 反码
00000000 00000000 00000000 00001010 补码
int num2 = -10;
10000000 00000000 00000000 00001010 源码
11111111 11111111 11111111 11110101 反码
11111111 11111111 11111111 11110110 补码
注:如果是负数的补码再转源码的话,先减一,在符号位不变其他位取反即可。
位运算
位运算操作数必须是整数,位运算操作的是二进制。
符号 | 含义 | 备注 |
---|---|---|
& | 按位与 | 两位都为1,结果才为1,否则为0 |
| | 按位或 | 两位有一位1,结果就为1。两位都是0,结果为0 |
^ | 异或 | 相同为0,相异为1 |
<< | 左移 | 左边溢出丢弃,右边补0 |
>> | 右移 | 1.逻辑右移 左边补0,右边溢出丢弃 2.算术右移 左边补符号位,右边溢出丢弃 |
int a = 10;
00000000 00000000 00000000 00001010 //10的补码
int b = -5;
10000000 00000000 00000000 00000101 //5的源码
11111111 11111111 11111111 11111010 //5的反码
11111111 11111111 11111111 11111011 //5的补码
a & b;
00000000 00000000 00000000 00001010 //10的补码
11111111 11111111 11111111 11111011 //5的补码
00000000 00000000 00000000 00001010 //a&b的结果是10
int a = 10;
00000000 00000000 00000000 00001010 //10的补码
int b = -5;
10000000 00000000 00000000 00000101 //5的源码
11111111 11111111 11111111 11111010 //5的反码
11111111 11111111 11111111 11111011 //5的补码
a | b;
00000000 00000000 00000000 00001010 //10的补码
11111111 11111111 11111111 11111011 //5的补码
11111111 11111111 11111111 11111011 //a|b补码
// 此时我们不容易看出结果 所以需要转换为源码来阅读
11111111 11111111 11111111 11111010 //a|b反码
10000000 00000000 00000000 00000101 //a|b源码 结果是-5
int a = 10;
00000000 00000000 00000000 00001010 //10的补码
int b = -5;
10000000 00000000 00000000 00000101 //5的源码
11111111 11111111 11111111 11111010 //5的反码
11111111 11111111 11111111 11111011 //5的补码
a ^ b;
00000000 00000000 00000000 00001010 //10的补码
11111111 11111111 11111111 11111011 //5的补码
11111111 11111111 11111111 11110001 //a^5补码
// 此时我们不容易看出结果 所以需要转换为源码来阅读
11111111 11111111 11111111 11110000 //a^5反码
10000000 00000000 00000000 00001111 //a^5源码 结果是-15
int a = 10;
00000000 00000000 00000000 00001010 //10的补码
a << 1
00000000 00000000 00000000 00010100 //左边溢出丢弃右边补0 结果2
int a = -10;
10000000 00000000 00000000 00001010 //-10的源码
11111111 11111111 11111111 11110101 //-10的反码
11111111 11111111 11111111 11110110 //-10的补码
a >> 1
111111111 11111111 11111111 1111011 //右边溢出丢弃左边补符号位
111111111 11111111 11111111 1111010
100000000 00000000 00000000 0000101 //结果-5