<< 左移操作符(左边抛弃、右边补0)
左移时逻辑移位和算术移位相同。
>> 右移操作符
逻辑移位:左边用0填充
算术移位:左边用原该值的符号位填充。
C标准说:
无符号数执行所有移位都是逻辑移位。
但对于有符号的数移位,采用哪种移位方式是根据编译器决定的。
使用技巧:(伪代码呈现)
求二进制最低位 使用(二进制数&1)的高效方法
若 x&(x-1) == 0 则 x为2的次方
对于a<<-4这种有歧义的语句尽量不要使用
# include <stdio.h>
# include <stdlib.h>
# include <math.h>
int main()
{
int num = 0;
int sum = 0;
int temp = 0;
int ret = 0;
printf("please input one number\n");
scanf_s("%d", &num);
for (int b = 0; b < 32; ++b)
{
temp = ((num >> b) & 1); /*利用位运算依次获取二进制最低位*/
ret = ((ret << 1) | temp); /*利用位运算较为高效的进行对翻转形式的数值转化*/
}
//sum += pow((float)2, (31 - b)) * temp; /*cpp中pow函数有类型的问题,所以对pow(x,y)中的x进行类型(double也行)强转;此外求和还可以利用位运算优化*/
printf("\n");
printf("%u\n", ret); /*一定是无符号输出 否则会超出有符号的最大值*/
return 0;
}
对于这个例子中 有以下论述:
1 在确定函数原型时 就应该使用无符号类型 否则在输出中添加
printf("%u\n", ret);
避免产生一个比较大的负数
2 核心代码解释
a; temp = ((num >> b) & 1);
&:(左值 右值同为1时 结果为1 二进制位不是1就是0 0&1 = 0;1&1= 1) 1的二进制编码为 0000 0000 0000 0000 0000 0000 0000 0001 任何二进制数位与1,即最低位记录
结合上文提到的求最低位技巧 在for的每次循环中 右移相应的位数 并记录最低位(临时记录)达到从右向左 使用二进制位的目的
b; ret = ((ret << 1) | temp);
|:(左值 右值有一个为1时 结果为1 1|1=1 0|1 =1 0|0=0) 将a中临时记录的最低位 左移(例如 0001 << 1 = 0010 即右边补0) 为或a中临时变量后 达到反转效果
(例子)伪代码如下:
ret = 0
输入NUM = 0111 NUM>>1 = 0011 0011& 0001 = 0001 临时记录 temp
ret(初始为0)<<1 = 0 0 | 0001(temp) = 0001(ret 0001)
NUM>>2=0001 0001 & 0001 = 0001(temp)
ret(0001) << 1 = 0010 0010 | 0001(temp) = 0011
.......
本例四次操作后 NUM 0111 反转为 1110
.......
for循环 32次结束后 0000 0000 0000 0000 0000 0000 0000 0111 -》 1110 0000 0000 0000 0000 0000 0000 0000
mian over