位运算概述

程序中所有的数在计算内存中都是以二进制的形式存储的,位运算是指按二进制进行的运算,位运算的运算速度通常与加法运算相同(仍快于乘法运算),但通常功耗较小,因为资源使用比较小。

在软件开发的过程中,常常要处理二进制的问题,例如:

  • 通过子网掩码求IP地址的网络号
  • 通过异或对数据进行加密
  • 通过单片机、STM32等控制灯光、风扇等
  • 通过位运算判断数据的奇偶性

任何二进制位的表示都从右侧(最低位)开始计数,向左进。例如:二进制值0001(十进制1)除第一位(即最右边)每位上都是0。

位运算符

下面分别对其进行说明:

  • 取反(~)
    取反是一元运算符,对一个二进制数的每一位执行逻辑反操作。使数字1成为0,0成为1。如正数~ 00000001 = 11111110。负数有一定的难度这里就不过多的说明了,有兴趣的同学可以自学一下。

  • 按位与(&)
    与运算符通常用于二进制的取位操作,相同位的两个数字都为1,则为1;若有一个不为1,则为0。如00000011 & 00000001 = 00000001

  • 按位或(or)
    或运算符通常用于二进制特定位上的条件赋值,相同位只要一个为1即为1。如00000111 | 00000001 = 000001111

  • 按位异或(^)
    异或通常用于对等长二进制模式按位或二进制数的每一位执行逻辑按位异或操作相同位不同则为1,相同则为0。如00000001 ^ 00000111 = 00000110

  • 左移运算符(<<)
    左移运算符是将二进制位全部进行左移操作(相当于左边的二进制位丢弃,右边的补0),例如:00000001 << 2 = 00000100,它的值也就相当于原数*2的位数次方,00000001表示十进制1的二进制位, 1 ∗ 2 2 = 4 1*2^2 = 4 122=4,4的二进制位表示为00000100。

  • 右移运算符(>>)
    右移运算符是将二进制位全部进行右移操作(正数左补0,负数左补1,右边丢弃),例如:正数0000100 >> 2 = 00000001,它的值也就相当于原数/2的位数次方,00000100表示十进制4的二进制位, 4 / 2 2 = 1 4/2^2 = 1 4/22=1,1的二进制位表示为00000001。负数10000100 >> 2 = 11100001

位运算的高级操作

1) 判断整数的奇偶性

一个数 & 1 ,如果结果为1,则原数为奇数;如果结果为0,则原数为偶数。

3 & 1  //相当于0011 & 1 = 0001 = 1,为奇数

4 & 1  //相当于0100 & 1 = 0000 = 0,为偶数

2)位操作进行高低位交换

a = (a >> 8)| (a << 8);

3)不使用中间变量交换两个整型变量的值

// 常规的数据交换
int a = 1,b = 6;
a = a + b;  //a = 7
b = a - b;  //b = 1
a = a - b;  //a = 6

// 用位运算
// a = 0001,b = 0110
int a = 1,b = 6;
a = a ^ b;  //a = 0111 = 7
b = a ^ b;  //b = 0001 = 1
a = a ^ b;  //a = 0110 = 6

4)数据的“组装”
假如我们拿到了被拆解的后的数据分别为:0x12 0x34 0x56 0x78,如何组装成0x12345678呢?

x = 0x12<<24 | 0x34<<16 | 0x56<<8 | 0x78

5)数据的“拆解”
在数据的传输过程中需要对整型数据进行拆解,例如 int x = 0x12345678, 我们需要将x分别拆解成0x12 0x34 0x56 0x78进行传输

int x = 0x12345678;
x & 0xFF;

(x >> 8) & 0xFF;
(x >> 16) & 0xFF;
(x >> 24) & 0xFF;
04-18 00:23