- << 左移操作符
- >> 右移操作符
注:移位操作符的操作数只能是整数。
移位操作符移动的是二进制位。
整数的二进制表示有3种:
- 原码
- 反码
- 补码
正的整数的原码、反码、补码相同。
负的整数的原码、反码、补码是要计算的。
- 由负整数原码计算出反码:原码的符号位不变,其他位按位取反。
- 由负整数反码计算出补码:反码+1。
示例:
7的原码、反码、补码:
- 原码:0000 0000 0000 0000 0000 0000 0000 0111
- 反码:0000 0000 0000 0000 0000 0000 0000 0111
- 补码:0000 0000 0000 0000 0000 0000 0000 0111
-7的原码、反码、补码:
- 原码:1000 0000 0000 0000 0000 0000 0000 0111
- 反码:1111 1111 1111 1111 1111 1111 1111 1000 符号位不变,其他位按位取反
- 补码:1111 1111 1111 1111 1111 1111 1111 1001 反码+1
整数在内存中存的是补码。
移位操作符移动的是存在内存中的补码。
1左移操作符
移位规则: 左边抛弃、右边补0。
正的整数左移示例:
对7左移
补码:0000 0000 0000 0000 0000 0000 0000 0111
左移:0000 0000 0000 0000 0000 0000 0000 1110
左移后内存中存的还是补码,因为正整数的原码和补码相同,所以对7左移后的值十进制为14。
代码验证:
#include <stdio.h>
int main()
{
int a = 7 ;
int b = a << 1;
printf("a=%d\n", a);
printf("b=%d\n", b);
return 0;
}
运行结果:
a=7
b=14
变量b得到了变量a左移1位之后的变化,但变量a自身是不变的。
负的整数左移示例:
对-7左移
补码:1111 1111 1111 1111 1111 1111 1111 1001
左移:1111 1111 1111 1111 1111 1111 1111 0010
左移后内存中存的还是补码,因为负整数的原码和补码之间需要计算。
- 由负整数补码计算出反码:补码-1。
- 由负整数反码计算出原码:反码的符号位不变,其他位按位取反。
补码:1111 1111 1111 1111 1111 1111 1111 0010 (左移1位后)
反码:1111 1111 1111 1111 1111 1111 1111 0001 补码-1
原码:1000 0000 0000 0000 0000 0000 0000 1110 符号位不变,其他位按位取反。
计算出-7左移后的值十进制为-14。
代码验证:
#include <stdio.h>
int main()
{
int a = -7 ;
int b = a << 1;
printf("a=%d\n", a);
printf("b=%d\n", b);
return 0;
}
运行结果:
a=-7
b=-14
因为二进制数的每一位都是2的指数幂,所以左移1位后,只要没有发生数据溢出,值就会变为原来的2倍,如果变量为无符号整形或正整数,表达式 a << n 会将a的所有位左移n位,运算结果位a×。
2 右移操作符
移位规则:
- 逻辑移位:左边补0,右边丢弃。
- 算术移位:左边补原值的符号位,右边丢弃。(绝大多数编译器采用算术移位,所以示例都为算数移位结果)
正的整数右移示例:
对7右移
补码:0000 0000 0000 0000 0000 0000 0000 0111
左移:0000 0000 0000 0000 0000 0000 0000 0011
右移后内存中存的还是补码,因为正整数的原码和补码相同,所以7左移后的值十进制为3。
代码验证:
#include <stdio.h>
int main()
{
int a = 7 ;
int b = a >> 1;
printf("a=%d\n", a);
printf("b=%d\n", b);
return 0;
}
运行结果:
a=7
b=3
负的整数右移示例:
对-7右移
补码:1111 1111 1111 1111 1111 1111 1111 1001
左移:1111 1111 1111 1111 1111 1111 1111 1100
右移后内存中存的还是补码,因为负整数的原码和补码之间需要计算。
- 由负整数补码计算出反码:补码-1。
- 由负整数反码计算出原码:反码的符号位不变,其他位按位取反。
补码:1111 1111 1111 1111 1111 1111 1111 1100 (左移1位后)
反码:1111 1111 1111 1111 1111 1111 1111 1011 补码-1
原码:1000 0000 0000 0000 0000 0000 0000 0100 符号位不变,其他位按位取反。
计算出-7右移后的值十进制为-4。
代码验证:
#include <stdio.h>
int main()
{
int a = -7 ;
int b = a >> 1;
printf("a=%d\n", a);
printf("b=%d\n", b);
return 0;
}
运行结果:
a=-7
b=-4
因为二进制数的每一位都是2的指数幂,所以右移1位后,只要没有发生数据溢出,值就会变为原来的二分之一,如果变量为无符号整形或正整数,表达式 a >> n 会将a的所有位右移n位,运算结果位a÷。
警告:对于移位运算符,不要移动负数位,这个是标准未定义的。