1.二进制位运算(嵌入式)

核心概念:

  • 位运算直接操作的是变量在内存中的二进制位 (0 或 1)。
  • 通常用于 unsigned 类型的整数,避免有符号数可能带来的复杂性 (尤其是右移)。
  • 常与十六进制 (0x...) 或二进制 (0b...,部分编译器支持) 表示法结合使用,更直观。

1. 按位非 (NOT) ~嵌入式

  • 作用: 对操作数的每一个二进制位进行取反操作 (0 变成 1,1 变成 0)。
  • 例子: C

    unsigned char a = 0b01010101; // 十进制是 85
    unsigned char result = ~a;     // result 会变成 0b10101010 (十进制是 170)
    
  • 注意: ~ 是一元运算符,只需要一个操作数。

2. 按位与 (AND) &

  • 作用: 对两个操作数的对应二进制位进行运算。只有当两个位都为 1 时,结果位才为 1,否则为 0。
  • 规则:
    • 0 & 0 = 0
    • 0 & 1 = 0
    • 1 & 0 = 0
    • 1 & 1 = 1
  • 例子: C

    unsigned char a = 0b11001100; // 0xCC
    unsigned char b = 0b10101010; // 0xAA
    unsigned char result = a & b;     // result 会变成 0b10001000 (0x88)
    //   11001100
    // & 10101010
    // -----------
    //   10001000
    
  • 常见用途 (非常重要!):
    • 清零特定位 (Masking): 将某位或某几位强制变为 0,其他位保持不变。方法是与一个特定位为 0,其余位为 1 的数 (称为“掩码” mask) 进行 AND 运算。 C

      unsigned char flags = 0b01101101;
      // 想要清除第 0 位和第 3 位 (从右往左数,从 0 开始)
      unsigned char mask = ~(0b00001001); // mask = 0b11110110
      flags = flags & mask;             // flags 变成 0b01100100
      
    • 检查特定位是否为 1: 判断某位是否被设置。方法是与一个只有该位为 1,其余位为 0 的数进行 AND 运算,如果结果不为 0,则该位为 1。 C

      unsigned char flags = 0b01101101;
      // 检查第 2 位是否为 1
      unsigned char mask = 0b00000100; // 只有第 2 位是 1
      if ((flags & mask) != 0) {
          // 第 2 位是 1
      } else {
          // 第 2 位是 0
      }
      

3. 按位或 (OR) |

  • 作用: 对两个操作数的对应二进制位进行运算。只要两个位中至少有一个为 1,结果位就为 1,否则为 0。
  • 规则:
    • 0 | 0 = 0
    • 0 | 1 = 1
    • 1 | 0 = 1
    • 1 | 1 = 1
  • 例子: C

    unsigned char a = 0b11001100; // 0xCC
    unsigned char b = 0b10101010; // 0xAA
    unsigned char result = a | b;     // result 会变成 0b11101110 (0xEE)
    //   11001100
    // | 10101010
    // -----------
    //   11101110
    
  • 常见用途 (非常重要!):
    • 设置特定位 (Setting): 将某位或某几位强制变为 1,其他位保持不变。方法是与一个特定位为 1,其余位为 0 的数进行 OR 运算。 C

      unsigned char flags = 0b01100100;
      // 想要设置第 1 位和第 7 位
      unsigned char mask = 0b10000010;
      flags = flags | mask;             // flags 变成 0b11100110
      

4. 按位异或 (XOR) ^

  • 作用: 对两个操作数的对应二进制位进行运算。当两个位不同时,结果位为 1,相同时为 0。
  • 规则:
    • 0 ^ 0 = 0
    • 0 ^ 1 = 1
    • 1 ^ 0 = 1
    • 1 ^ 1 = 0
  • 例子: C

    unsigned char a = 0b11001100; // 0xCC
    unsigned char b = 0b10101010; // 0xAA
    unsigned char result = a ^ b;     // result 会变成 0b01100110 (0x66)
    //   11001100
    // ^ 10101010
    // -----------
    //   01100110
    
  • 常见用途:
    • 翻转特定位 (Toggling): 将某位或某几位的值翻转 (0 变 1,1 变 0),其他位保持不变。方法是与一个特定位为 1,其余位为 0 的数进行 XOR 运算。 C

      unsigned char led_state = 0b00000001; // 假设表示 LED 亮
      // 想要翻转第 0 位 (开关 LED)
      unsigned char mask = 0b00000001;
      led_state = led_state ^ mask; // 第一次变成 0b00000000 (灭)
      led_state = led_state ^ mask; // 第二次变回 0b00000001 (亮)
      
    • 比较两个数是否相等: a ^ b == 0 当且仅当 a == b
    • 不使用临时变量交换两个数: a = a ^ b; b = a ^ b; a = a ^ b; (了解即可,现代编译器优化可能使其不必要)。
    • 简单的校验和或加密算法。

5. 左移 (Left Shift) <<

  • 作用: 将操作数的所有二进制位向左移动指定的位数。右边空出的位用 0 填充,左边移出的位被丢弃。
  • 例子: C

    unsigned char a = 0b00001101; // 十进制 13
    unsigned char result = a << 2;    // 左移 2 位, result 变成 0b00110100 (十进制 52)
    // 00001101 << 2  =>  00110100
    
  • 效果: 左移 N 位相当于乘以 2N (只要结果不溢出)。例如 x << 1 相当于 x * 2x << 3 相当于 x * 8。这在嵌入式中通常比乘法指令更快。
  • 常用于: 快速乘以 2 的幂,以及构造掩码 (例如 1 << n 可以生成一个只有第 n 位是 1 的数)。

6. 右移 (Right Shift) >>

  • 作用: 将操作数的所有二进制位向右移动指定的位数。左边空出的位如何填充取决于操作数的类型:
    • 逻辑右移 (Logical Shift): 对于 unsigned 无符号类型,左边空出的位总是用 0 填充。
    • 算术右移 (Arithmetic Shift): 对于 signed 有符号类型,左边空出的位用符号位填充 (即,如果原数是负数,通常用 1 填充;如果是正数,用 0 填充)。这是为了保持数的正负性。
  • 例子 (Unsigned): C

    unsigned char a = 0b11100100; // 十进制 228
    unsigned char result = a >> 2;    // 右移 2 位, result 变成 0b00111001 (十进制 57)
    // 11100100 >> 2  =>  00111001 (左边补 0)
    
  • 例子 (Signed - 依赖编译器实现,但通常如下): C

    signed char b = -28; // 二进制补码表示通常为 0b11100100 (假设 8 位)
    signed char result_signed = b >> 2; // 右移 2 位, result 可能是 0b11111001 (十进制 -7)
    // 11100100 >> 2  =>  11111001 (左边补符号位 1)
    
  • 效果: 右移 N 位相当于整数除以 2N (对于正数和无符号数)。例如 x >> 1 相当于 x / 2x >> 2 相当于 x / 4。比除法指令更快。
  • 常用于: 快速除以 2 的幂,获取某个位的值 (配合 &)。

总结与实践

掌握位运算的关键在于理解每个运算符的规则,并记住它们的常用场景:

  • & 用于 清零检查 位。
  • | 用于 设置 位。
  • ^ 用于 翻转 位。
  • << 用于快速 2 的幂,构造掩码。
  • >> 用于快速 2 的幂,提取位。
  • ~ 用于 取反 所有位。

小练习:

假设我们有一个 8 位的寄存器 CONTROL_REG,它的定义如下:

  • Bit 7: Enable (1 = Enabled, 0 = Disabled)
  • Bit 6: Interrupt Mask (1 = Masked, 0 = Unmasked)
  • Bit 5: Reserved
  • Bit 4: Mode Select (1 = Mode A, 0 = Mode B)
  • Bit 3-0: Clock Divider (0-15)

现在 CONTROL_REG 的值是 0b01011011。请思考如何用位运算实现以下操作?

  1. Enable the device (设置 Bit 7 为 1)。
  2. Disable the device (清除 Bit 7 为 0)。
  3. Check if the device is currently enabled (检查 Bit 7 的值)。
  4. Set the mode to Mode A (设置 Bit 4 为 1)。
  5. Toggle the Interrupt Mask (翻转 Bit 6)。
  6. Get the current Clock Divider value (提取 Bit 3-0 的值)。
  7. Set the Clock Divider value to 5 ( 0b0101 ) (需要先清零再设置)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值