目录
一、移位操作符
1.整数的二进制表示形式(原码,反码,补码)
整数的二进制表示形式有三种:原码,反码,补码。
计算机内存中存的是补码。
1)正数的原码,反码,补码相同。
以12为例(32位机器下):
原码:0000 0000 0000 0000 0000 0000 0000 1100
反码:0000 0000 0000 0000 0000 0000 0000 1100
补码:0000 0000 0000 0000 0000 0000 0000 1100
2)负数
负数的原码,反码,补码是需要通过计算的。
以-10为例:
原码:1000 0000 0000 0000 0000 0000 0000 1010
原码最左边的是符号位,1表示负数,0是正数。
反码:1111 1111 1111 1111 1111 1111 1111 0101
反码是原码的符号位不变,其他位按位取反
补码:1111 1111 1111 1111 1111 1111 1111 0110
补码是反码+1
2.<<左移操作符
注:移位操作符的操作数只能是整数。
移位规则:左边抛弃,右边补零。
1)正数
int a = 10;
int b = a <<1;
此时b的值是20,a不变,还是10。
2)负数
3.>>右移操作符
移位规则:右移运算分两种,具体哪一种取决于编译器,大多数时候是第一种。
1,算术位移:右边丢弃,左边用原该值的符号位填充。
2,逻辑位移:右边丢弃,左边补零。
警告:对于移位运算符,不要移动负数位,这个是标准未定义的
如:b = a>>-2 (不能这么写)
二、位操作符
位操作符有:
&:按位与
| :按位或
^ :按位异或
注:他们的操作数必须是整数。
1.按位与&
对应的二进制位,有0则为0,两个同时为1,才为1。
例如:
#include <stdio.h>
int main()
{
int a = 3;
//0000 0000 0000 0000 0000 0000 0000 0011
int b = -5;
//1000 0000 0000 0000 0000 0000 0000 0101 -原码
//1111 1111 1111 1111 1111 1111 1111 1010 -反码
//1111 1111 1111 1111 1111 1111 1111 1011 -补码
int c = a & b;
//0000 0000 0000 0000 0000 0000 0000 0011 -a的补码
//1111 1111 1111 1111 1111 1111 1111 1011 -b的补码
//有0则0,两1才1
//0000 0000 0000 0000 0000 0000 0000 0011
//c的补码,因为符号位为0,是正数,所以原码=补码
printf("%d\n", c);//c的值是3
return 0;
}
2.按位或 |
有1则为1,两个同时为0,才为0。
#include <stdio.h>
int main()
{
int a = 3;
//0000 0000 0000 0000 0000 0000 0000 0011
int b = -5;
//1000 0000 0000 0000 0000 0000 0000 0101 -原码
//1111 1111 1111 1111 1111 1111 1111 1010 -反码
//1111 1111 1111 1111 1111 1111 1111 1011 -补码
int c = a | b;
//0000 0000 0000 0000 0000 0000 0000 0011 -a的补码
//1111 1111 1111 1111 1111 1111 1111 1011 -b的补码
//有1则1,两0才0
//1111 1111 1111 1111 1111 1111 1111 1011
//c的补码,跟b的补码一样,所以c是-5。
printf("%d\n", c);
return 0;
}
3.按位异或^
对应二进制位相同为0,相异为1。
int main()
{
int a = 3;
//0000 0000 0000 0000 0000 0000 0000 0011
int b = -5;
//1000 0000 0000 0000 0000 0000 0000 0101 -原码
//1111 1111 1111 1111 1111 1111 1111 1010 -反码
//1111 1111 1111 1111 1111 1111 1111 1011 -补码
int c = a ^ b;
//0000 0000 0000 0000 0000 0000 0000 0011 -a的补码
//1111 1111 1111 1111 1111 1111 1111 1011 -b的补码
//1111 1111 1111 1111 1111 1111 1111 1000 -c的补码
//1000 0000 0000 0000 0000 0000 0000 1000 -c的原码
printf("%d\n", c);//c的值是-8
return 0;
}
不创建临时变量实现两个数的交换
首先,看两个比较妙的表达式:
1.a^a=0
0000 0000 0000 0000 0000 0000 0000 0011 ---3的补码
0000 0000 0000 0000 0000 0000 0000 0011 ---3的补码
0000 0000 0000 0000 0000 0000 0000 0000 ---0
2.0^a=a
0000 0000 0000 0000 0000 0000 0000 0000
0000 0000 0000 0000 0000 0000 0000 0011 ---3的补码
0000 0000 0000 0000 0000 0000 0000 0011 ---3
3.异或是支持交换律的。
#include <stdio.h>
int main()
{
int a = 5;
int b = 6;
a = a ^ b;
b = a ^ b;//a^b^b=a^0=a
a = a ^ b;//a^b^a=0^b=b
printf("%d %d", a, b);
return 0;
}
ps:上面的这种方法可读性差,效率其实也不如使用临时变量的方法。