11   学习位运算

1  位运算符(操作二进制位的基本工具)

1.1 运算符分类及功能

运算符

功能

运算规则

补充说明

&

按位与

对应位都为 1 时,结果为 1;否则为 0

可用于 “保留指定位”“清零指定位”

`

`

按位或

对应位至少有 1 个为 1 时,结果为 1

可用于 “设置指定位为 1”

^

按位异或

对应位不同为 1,相同为 0

可用于 “翻转指定位”“交换变量”

~

按位取反

0 变 1,1 变 0

单目运算符,结果与原数符号相反

<<

左移

二进制位整体左移,右侧补 0

相当于 “乘以 2ⁿ”(不溢出时)

>>

右移

分两种情况:
- 有符号数:左侧补符号位(正数补 0,负数补 1)
- 无符号数:左侧补 0

正数右移相当于 “除以 2ⁿ”(向下取整)

1.2 特殊应用详解

  • 按位异或交换两个数

    a = a ^ b;  
    b = a ^ b;  // 等价于 b = (a^b)^b = a(消去b)  
    a = a ^ b;  // 等价于 a = (a^b)^a = b(消去a)

        优势:不占用额外空间(无需临时变量)
        注意:若ab指向同一块内存(如aa交换),结果会变为 0,需避免这种场景

1.3 优先级规则(从高到低)

~(取反) → <</>>(移位) → &(按位与) → ^(按位异或) → |(按位或)

  • a | b & c 等价于 a | (b & c)(先算&

  • ~a << 2 等价于 (~a) << 2(先算~

1.4 位操作典型场景(核心应用)

1、置位操作(设置指定位为 1)

num的第n位(从 0 开始计数,最低位为第 0 位)设为 1:

num |= (1 << n);  // 1<<n生成“第n位为1,其余为0”的掩码,与num按位或后第n位必为1

例:将num=5(101)的第 1 位设为 1 → 5 | (1<<1) = 5 | 2 = 7(111)

2、清零操作(设置指定位为 0

num的第n位设为 0:

num &= ~(1 << n);  // ~(1<<n)生成“第n位为0,其余为1”的掩码,与num按位与后第n位必为0

例:将num=7(111)的第 1 位设为 0 → 7 & ~2 = 7 & 5 = 5(101)

3、取指定位的值

判断num的第n位是 0 还是 1:

int bit = (num >> n) & 1;  // 右移n位后与1按位与,结果为1则该位是1,否则为0

2  位运算示例(基于 32 位有符号整数)

2.1 按位与(&

num = 9 & 6;

  • 9 的二进制:0000 0000 0000 0000 0000 0000 0000 1001

  • 6 的二进制:0000 0000 0000 0000 0000 0000 0000 0110

  • 按位与结果:0000 0000 0000 0000 0000 0000 0000 0000 → num = 0

2.2 按位或(|

num = 9 | 6;

  • 9 的二进制:... 1001

  • 6 的二进制:... 0110

  • 按位或结果:... 1111 → 十进制 15 → num = 15

2.3 按位异或(^

num = 9 ^ 5;(替换原示例,避免与|结果巧合一致)

  • 9 的二进制:... 1001

  • 5 的二进制:... 0101

  • 按位异或结果:... 1100 → 十进制 12 → num = 12

2.4 左移(<<

num = 9 << 3;

  • 9 的二进制:... 1001

  • 左移 3 位:... 1001 000(右侧补 0) → 十进制 72 → num = 72

  • 注意:若左移导致溢出(如 32 位 int 的1 << 31会变成负数),结果不再等于 “乘以 2ⁿ”

2.5 右移(>>

  • 正数右移:num = 9 >> 3;
    9 的二进制:... 1001 → 右移 3 位:... 0001(补 0) → num = 1(9÷8=1.125,向下取整)

  • 负数右移(算术右移):num = -9 >> 3;
    -9 的补码:1111 ... 1111 0111 → 右移 3 位(补 1):1111 ... 1111 1110 → 十进制 - 2(与 - 9÷8=-1.125 的取整结果不同,需注意)

2.6 按位取反(~

num = ~9;

  • 9 的补码:0000 ... 0000 1001

  • 取反后补码:1111 ... 1111 0110(负数)

  • 转原码:符号位不变,其余位取反加 1 → 1000 ... 0000 1010 → 十进制 - 10 → num = -10

3  关键补充说明

3.1 位运算 vs 逻辑运算

类型

操作对象

结果范围

示例对比(a=3 即 11,b=5 即 101)

位运算

二进制位(逐位)

与操作数同类型

a & b = 1(001);`a

b = 7`(111)

逻辑运算

整体真假(0 为假,非 0 为真)

0 或 1(int)

a && b = 1;`a

b = 1`

3.2 效率与适用场景

  • 效率:位运算(如<</>>)比乘除运算快,因硬件直接支持二进制移位

  • 典型场景

    • 底层硬件控制(寄存器位操作)

    • 状态标志位(用 1 位表示一个开关状态,节省内存)

    • 权限控制(如用 8 位二进制表示 8 种权限)

    • 数据压缩 / 加密(基于位的算法)

    • 奇偶校验(num & 1判断奇偶:结果为 1 是奇数,0 是偶数)

3.3 常见误区

  • 位数计数从 0 开始(最低位是第 0 位,非第 1 位)

  • 右移对负数的处理与除法不同(算术右移可能导致结果偏差)

  • 异或交换变量并非绝对安全(同地址变量会出错)

  • 左移可能导致符号位变化(有符号数溢出后结果不可控)

Logo

openvela 操作系统专为 AIoT 领域量身定制,以轻量化、标准兼容、安全性和高度可扩展性为核心特点。openvela 以其卓越的技术优势,已成为众多物联网设备和 AI 硬件的技术首选,涵盖了智能手表、运动手环、智能音箱、耳机、智能家居设备以及机器人等多个领域。

更多推荐