二进制与位操作符、位移操作符
1、二进制
1.1 二进制与十进制
二进制其实就是十进制的另一种表现形式,十进制满10进1,二进制满2进1,十进制数字用0~9表示,二进制用0、1表示。
1.2 二进制与十进制之间的转换
1.2.1二进制转十进制
在十进制中,十进制的每一位都有权重,个位的权重是10的0次方,十位的权重是10的1次方,百位的权重是10的2次方…以此类推。例如十进制数321,它可以表示成每一位数字乘以它的权重之和。
同样的,二进制的每一位也有权重,例如,二进制数1011,从右往左数,第一位的权重是2的0次方,第二位的权重是2的1次方…以此类推。
根据二进制的权重,就能将二进制数转换成十进制数。
1.2.2 十进制转二进制
有两个方法:
1、短除法
将十进制数除以二,得到的商接着除以2,每次相除得到的余数写在最右边,直到除不过2为止
2、万能的计算器!
Windows键+r,输入calc后回车
切换成程序员即可。
bin表示二进制,dec表示十进制
1.3 原码、反码和补码
整数的二进制形式有原码、反码、补码。
- 整数在内存中,存放的是补码
- 对于有符号整数来说,二进制的最高位是符号位,正数的符号位是0,负数的符号位是1。
- 正数的原码、反码、补码都相同。
- 负数的原码、反码、补码则不同
原码:直接将十进制数转换成为二进制后的二进制数
反码:将原码的除符号位外,其他位进行按位取反(0变成1,1变成0)
补码:反码+1
- 反码得到原码的操作:反码取反(除符号位)、+1
例如:
十进制数 -5
原码 10000101
反码 11111010 原码按位取反
补码 11111011 反码+1
2、位移操作符、位操作符
位移操作符和位操作符的操作数只能是整数,操作的是二进制位。
- 注意:这些操作符都是基于补码进行操作,而printf输出的是原码
2.1 位移操作符
位移操作符包括左移操作符(<<)和右移操作符(>>)
左移 << 将二进制位的补码往左移动,左边丢弃,右边补0
右移 >> 分为逻辑右移和算术右移
逻辑右移 左边补0,右边丢弃
算术右移 左边补原来的符号位的值,右边丢弃
例:
#include<stdio.h>
int main()
{
int a=-5;
int b1=a<<1;
int b2=a>>1;
printf("%d\n",b1);//-10
printf("%d\n",b2);//-3
return 0;
}
-5的 补码 11111011
a<<1 11110110
10001010 -->转换成原码-10
a>>1 01111101 逻辑右移
00000011 -->转换成原码3
11111101 算术右移
10000011 -->转换成原码-3
输出结果
2.2 位操作符:& | ^ ~
2.2.1 按位与 &
都为1则为1,否则为0
#include<stdio.h>
int main()
{
int a = 5;
int b = 7;
//5 0101
//7 0111
//a & b 0101 5
int c = a & b;
printf("%d\n",c);
}
2.2.2 按位或 |
只要有一个是1,则为1,否则为0
#include<stdio.h>
int main()
{
int a = 5;
int b = 7;
//5 0101
//7 0111
//a | b 0101 7
int c = a | b;
printf("%d\n",c);
}
2.2.3 按位异或 ^
相异为1,否则为0
#include<stdio.h>
int main()
{
int a = 5;
int b = 7;
//5 0101
//7 0111
//a ^ b 0010 2
int c = a ^ b;
printf("%d\n",c);
}
2.2.4 按位取反 ~
0变1,1变0
#include<stdio.h>
int main()
{
int a=5;
int b=~a;
//5 0101
//~5 1010 -->补码
// 1110 -->原码-6
printf("%d\n");
return 0;
}
3、 补充
运算规则
n^0=n;
n^n=0;
a^b=b^a;
(a^b)^c=a^(b^c)
n&(n-1)
n&(n-1)
效果是将二进制中最右边的一个1消去