常用位运算总结


前言

位运算:从现代计算机中所有的数据二进制的形式存储在设备中。即0、1两种状态,计算机对二进制数据进行的运算(+、-、*、/)都是叫位运算,即将符号位共同参与运算的运算


一、按位与(&)

运算规则:参加运算的两个操作数(二进制模式),只有当相应位上全部为1时取1, 存在0时为0

 1&1=1  1&0=0 0&1=0 0&0=0
 1110 &0100 = 0100

注:与这个两个的区别
&&:逻辑与,运算符两边的表达式的值都为true运算结果为true, 其余情况为false

||:逻辑或
运算符两边的表达式的值都为false运算结果为false, 其余情况为true

与运算的作用:
1.清零
如果想将某位清零,即使其全部二进制位为0,只要与一个各位都为零的数值相与,结果为零

led &=0XFF0F; //将led第 4-7 位清 0

2.取一个数的指定位

led = 1101 0111
led & 0000 1111  = 0000 0111 //取led的低四位,

取某个数x的低几位,只需要另找一个数y,令y的低几位为1,其余位为0,然后将x与y进行按位与运算(x&y)即可得到x的指定位

3.判断奇偶
只要根据最未位是0还是1来决定,为0就是偶数,为1就是奇数。因此可以用if ((a & 1) == 0)代替if (a % 2 == 0)来判断a是不是偶数。

二、按位或(|)

运算规则:参加运算的两个操作数(二进制模式),只要当相应位上存在1时取1, 全部为0时为0

1101 0101 | 0010 0010 = 1111 0 111

作用:
置1:常用来对一个数据的某些位设置为1

led | 0000 1111 将led的低四位置1

三、按位异或(^)

运算规则:参加运算的两个操作数(二进制模式),只有当相应位上的数字不相同时取1, 相同为0

1^1 = 0 0^0 = 0 0^1=1^0 = 1

作用:
1.翻转指定位(与1相异或值变化)
比如将数 X=1010 1110 的低4位进行翻转,只需要另找一个数Y,令Y的低4位为1,其余位为0,即Y=0000 1111,然后将X与Y进行异或运算(X^Y=1010 0001)即可得到。

2.与0相异或值不变

1010 1110 ^ 0000 0000 = 1010 1110

3.交换两个数

void Swap(int &a, int &b)
{
    if (a != b)
    {
        a ^= b;
        b ^= a;
        a ^= b;
    }
}

四、按位异或(⊙)

运算规则:参加运算的两个操作数(二进制模式),只有当相应位上的数字相同时取1, 不相同为0

11 = 00 = 1 01=10 = 0

五、按位取反(~)

运算规则:操作数(二进制模式),0变1,1变0

~(1001) = 0110

六、左移(<<)

运算规则:将一个运算对象的各二进制位全部左移若干位,左边的二进制位丢弃,右边补0

a=1010 1110
a = a<< 2 //将a的二进制位左移2位、右补0,即得a=1011 1000

b = 3
b = b<<2  // b = 3*2^2

操作数每左移一位,相当于该数乘以2

七、右移(>>)

运算规则:将一个数的各二进制位全部右移若干位,正数左补0,负数左补1,右边丢弃

操作数每右移一位,相当于该数除以2

八、单片机中的应用

1.不改变其他位的值的状况下,对某几个位进行设值
这个场景单片机开发中经常使用,方法就是先对需要设置的位用 &= 操作符进行清零操作,然后用 |= 操作符设值。

比如要改变 GPIOA-> BSRRL 的状态,可以先对寄存器的值进行&清零操作

GPIOA-> BSRRL &=0XFF0F; //将第 4-7 位清 0

然后再与需要设置的值进行|或运算

GPIOA-> BSRRL |=0X0040;//设置相应位的值,不改变其他位的值

2.移位操作
将 ODR 寄存器的第 pinpos 位设置为 1

GPIOx->ODR = (((uint32_t)0x01) << pinpos);

3.异或操作
可以利用与0相异或值不变,与1相异或值变化

每一次进行异或等于进行反转电平

// 外部中断回调函数, 产生外部中断,会跳转到外部中断的中断处理函数
// 中断处理函数又调用回调函数,进行中断处理
// 每触发一次进入外部中断
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
	/* uclde = 0000 0000 ^ 1000 1000 =1000 1000  (1)
	   ucled = 1000 1000 ^ 1000 1000 = 0000 0000  (2)
		uclde = 0000 0000 ^ 1000 1000 = 1000 1000  (3)
	 如此下去继续反转
	与0相异或值不变,与1相异或值变化
	*/
	ucLed ^= 0x88;  //ucLed 刚开始位0 最高位和第四位电平一直反转,其余不变
	LED_Display(ucLed);
}

总结

提示:这里对文章进行总结:

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Super.Bear

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值