目录
移位操作符
1.整数的二进制表示形式
整数的二进制表示形式有3种:原码、反码和补码
一个整数是4个字节也就是32bit位,所以一个整数写成二进制序列就是32个bit位
而对于有符号的整数来说,最高位(从左边数第一个)的那1位是符号位:
符号位是1,表示为负数。
符号位是0,表示为正数。
但对于无符号整数来说,没有符号位一说,所有位都是有效位。(无符号嘛,只能表示正数)
对于正的整数来说, 原码、反码、补码相同,无需计算。
对于负的整数来说,原码、反码、补码是需要计算的。
下面我们来谈谈原码、反码和补码。
2.原码 、反码和补码
-
原码
概念:按照数值的正负,直接写出的二进制序列就是原码。
举个列子:
-
反码
概念:原码的符号位保持不变,其他位按位取反
如下:
-
补码
概念:反码的二进制序列+1,得到的即为补码
如下:
注:整数在内存中存储的都是其补码的二进制序列。
整数在计算的时候也是使用的补码。(很重要)
左移和右移操作符
//左移
int main()
{
int m = 7;
int n = m << 1;
printf("%d\n", n);
printf("%d\n",m);
return 0;
}
这里我们来解析下左移的过程。
1.左移过程
运算规则:左边丢弃,右边补0
这里通过代码运行结果也可验证:
这里m只是参与运算,所以其本身的值并不会改变。
而通过最终的结果可以看到,左移一位相当于原来的值乘2。
下面看负数左移的过程
int main()
{
int m = -7;
int n = m << 1;
printf("%d\n", n);
printf("%d\n",m);
return 0;
}
结果:
2.右移过程
两种右移方式:
- 算术右移
- 逻辑右移
int main()
{
int a = -10;
int b = a >> 1;
printf("a=%d\n", a);
printf("b=%d\n", b);
}
运行结果:
可知,编译器采用的为算术右移。这里注意:不同的编译器可能选择不同的右移方式。
位操作符
& 按位与
| 按位或
^ 按位异或
注意:它们的操作数只能是整数
1.& 按(二进制位)与操作
运算规则:1&1=1;1&0=0;0&1=0;0&0=0
int main()
{
int a = 3;
int b = -5;
int c = a & b;
//00000000000000000000000000000011--3的补码
//11111111111111111111111111111011-- -5的补码
//00000000000000000000000000000011--按位与操作后
printf("%d\n", c);
}
可知c的结果为:3
- 获取最低位的方法
int main()
{
int a = 3;
int ch = a & 1;
//如此可得最低位的数字是什么
printf("%d\n", ch);
return 0;
}
由此可知3的二进制序列最低位是:1
2.| 按(二进制位)或操作
运算规则:0 | 0= 0 , 1 | 0= 1 , 0 | 1= 1 , 1 | 1= 1
int main()
{
int a = 3;
int b = -5;
int c = a | b;
//00000000000000000000000000000011--3的补码
//11111111111111111111111111111011-- -5的补码
//11111111111111111111111111111011--按位或操作后所得补码
//10000000000000000000000000000101--转为了原码
printf("%d\n", c);
return 0;
}
可知c的结果为:-5
3.^ 按(二进制位)异或操作
运算规则:两数相同为0,相异为1
int main()
{
int a = 3;
int b = -5;
int c = a ^ b;
// 00000000000000000000000000000011--3的补码
// 11111111111111111111111111111011-- -5的补码
// 11111111111111111111111111111000--按位异或后所得补码
// 10000000000000000000000000001000--转为了原码
printf("%d\n", c);
return 0;
}
可知c的结果为:-8
总结:学习这部分知识时,建议大家先提前了解下10进制与2进制间的相互转换,这样学这部分内容时理解的会更深刻。