位运算操作符详解
文章目录
- 一. 移位操作符>> <<
-
- 1. 整数的二进制表示
-
-
-
-
- Ps:怎么确定一个数在内存中占几位呢?
-
-
-
- 2. <<左移操作符
- 3. >>右移操作符
- 二. 位操作符& |^
-
- 1. &按(二进制)位与
- 2. |按(二进制)位或
- 3. ^按(二进制)位异或
-
- 1.异或用在解题中用到的性质:
- 2.位操作符的应用
-
-
- (1) 使特定位翻转
- (2)不用中间变量,实现两个数的交换
- (3) 找到只出现特定次数的数字
-
一. 移位操作符>> <<
操作数只能是整数
对于移位运算符,不要移动负数位,这是标准未定义的
num>>-1//ERROR
1. 整数的二进制表示
整数的二进制有3种表示:
1. 原码1. 反码1. 补码
最高位是符号位,0表示为正数,1表示为负数
Ps:怎么确定一个数在内存中占几位呢?
比如int型整数,占4个字节,每个字节是8比特,所以占4*8=32比特位
int 5的原码:00000000 00000000 00000000 00000101
int -5的原码:10000000 00000000 00000000 00000101
同理,char型是1个字节,就占8位
正整数 | 负整数 | |
---|---|---|
原码 | 数在内存中的二进制,最高位为0 | 最高位为1 |
补码 | 与原码相同 | 原码符号位不变,其他位按位取反 |
反码 | 与原码相同 | 反码+1 |
int a = -5
原码:10000000 00000000 00000000 00000101
反码:11111111 11111111 11111111 11111010
补码:11111111 11111111 11111111 11111011
整数在内存里存储的是补码,打印出来的值是原码
2. <<左移操作符
移位规则:
左边抛弃、右边补0
int a = -10;int b = a<<1;//左移一位printf("%d\n",a);printf("%d\n",b);
结果是:
-10
-20
注意:a本身值是不变的
左移n位就是把原数值*2的n次方
一整个计算过程是这样的
这是负数的情况,如果是正数,原、补、反码都一样,到了第4步就不必再-1、取反了。
3. >>右移操作符
移位规则:
右移有两种:
- 算数右移:右边丢弃,左边补原符号位
- 逻辑右移:右边丢弃,左边补0
是算数右移还是逻辑右移取决于编译器
二. 位操作符& |^
操作数只能是整数
1. &按(二进制)位与
int a = 3;int b = -5;int c = a&b;
a和b的补码相运算
对应二进制位上,a和b中只有一个有0就为0,两个都为1时才为1
真值表:
& | 0 | 1 |
---|---|---|
0 | 0 | 0 |
1 | 0 | 1 |
00000000 00000000 00000000 00000011 -> a=3的补码11111111 11111111 11111111 11111011 -> b=-5的补码00000000 00000000 00000000 00000011 -> c的补码同样,输出是原码,这里最高位是0,是正数,所以原码和补码相同
c=3
2. |按(二进制)位或
int a = 3;int b = -5;int c = a|b;
对应二进制位上,a和b中有1就为1
真值表:
| | 0 | 1 |
---|---|---|
0 | 0 | 1 |
1 | 1 | 1 |
00000000 00000000 00000000 00000011 -> a=3的补码11111111 11111111 11111111 11111011 -> b=-5的补码11111111 11111111 11111111 11111011 -> c的补码我们来求c的输出11111111 11111111 11111111 11111010 -> c的反码10000000 00000000 00000000 00000101 -> c的原码
c=-5
3. ^按(二进制)位异或
int a = 3;int b = -5;int c = a^b;
对应二进制位上,相同为0,相异为1
真值表:
^ | 0 | 1 |
---|---|---|
0 | 0 | 1 |
1 | 1 | 0 |
00000000 00000000 00000000 00000011 -> a=3的补码11111111 11111111 11111111 11111011 -> b=-5的补码11111111 11111111 11111111 11111000 -> c的补码我们来求c的输出11111111 11111111 11111111 11110111 -> c的反码10000000 00000000 00000000 00001000 -> c的原码
c=-8
1.异或用在解题中用到的性质:
- 任何数与0异或仍是它本身
- 任何数与1异或等于将其取反
- 任何数与自己异或,等于把自己置0
- 异或满足交换律、结合律
2.位操作符的应用
(1) 使特定位翻转
比如:01111010,想使其低4位翻转,即1变为0,0变为1。可以将它与00001111进行^运算
(2)不用中间变量,实现两个数的交换
#include int main(){ int a = 10; int b = 20; a = a^b;//1 b = a^b;//2 a = a^b;//3 printf("a = %d b = %d\n", a, b); return 0;}//可以这样理解,将1代入2//b = a^b^b //b = a//将2代入3//a = a^a^b //a = b
(3) 找到只出现特定次数的数字
一道面试题大家可以试着做做看:https://leetcode-cn.com/problems/missing-number-lcci
参考:https://blog.csdn.net/wwt18811707971/article/details/