当前位置: 首页 > news >正文

c语言中使用(>> )运算替代(/ %)运算实现优化

在 C 语言中,使用位运算 >>(右移)和 &(按位与)来代替除法 / 和取模 % 运算,主要是因为位运算在某些情况下比算术运算更高效。具体原因如下:

1. 位运算速度更快

  • 右移 >> 相当于除以 2 的幂,例如 x >> 1 相当于 x / 2x >> 2 相当于 x / 4,以此类推。
  • 按位与 & 操作可以用于取模运算,但只能用于模 2 的幂的情况。例如 x % 32 可以使用 x & 0x1F 来替代,x % 4 可以使用 x & 0x03
  • 在大多数处理器架构中,除法和取模运算通常比位移和按位与运算要慢。因为除法涉及更复杂的硬件操作,而位运算直接操作二进制位,硬件执行起来更快。

2. 位运算的常见优化

  • 除以 2 的幂次方: 用右移 >> 代替除法 /。例如,x / 8 等价于 x >> 3
  • 取模 2 的幂次方: 用按位与 & 代替取模 %。例如,x % 32 等价于 x & 31

这种优化在嵌入式编程、驱动程序开发和操作系统内核代码中尤其常见,因为这些领域对性能有很高的要求。

3. 代码示例

extern __inline__ int test_bit(int nr, const unsigned long * addr)
{int	mask;addr += nr >> 5;mask = 1 << (nr & 0x1f);return ((mask & *addr) != 0);
}

test_bit 函数用于检测位数组中某一位是否被设置(即为1)。

实现步骤

  • 确定要访问的 unsigned long 元素:

    addr += nr >> 5;
    
    • 这里的 nr >> 5 实际上是将 nr 右移5位,这相当于 nr / 32。因为一个 unsigned long 通常占 4 字节(32 位),所以右移5位就可以确定 nr 所在的 unsigned long 元素的索引位置。
    • 例如,如果 nr 是 35,那么 nr >> 5 等于 1,这意味着你要访问位数组中的第二个 unsigned long 元素(因为数组索引从0开始)。
  • 计算要测试的位的掩码:

    mask = 1 << (nr & 0x1f);
    • nr & 0x1f 是对 nr 取低5位,这相当于 nr % 32,即计算 nr 在当前 unsigned long 元素中的位置。
    • 1 << (nr & 0x1f) 是将数字1左移到 nr 在当前 unsigned long 元素中对应的位置。例如,如果 nr & 0x1f 结果为 3,则 mask = 1 << 3 = 0b1000,即第4位是1。
  • 进行位测试:

    return ((mask & *addr) != 0);
    • *addr 取当前的 unsigned long 元素的值。
    • 然后通过 mask & *addr 来检查 mask 对应的那一位是否在 *addr 中被设置为1。
    • 如果 mask 对应的位为1,则返回 1,否则返回 0

4. 优点总结

  • 效率高:位移和按位与的计算通常只需要一个 CPU 指令,而除法和取模则可能需要多个指令甚至硬件支持,因此性能差异明显。
  • 简洁:位运算在处理固定大小的块或需要快速循环/分配资源时更加简洁和易于控制。

5. 注意事项

  • 适用范围有限:位运算优化只适用于 2 的幂次方情况。例如,如果除数或模数不是 2 的幂,不能直接使用 >>& 来代替。
  • 代码可读性:尽管位运算更高效,但过多使用位运算可能降低代码的可读性,尤其对于不熟悉位运算的人来说。

6. 硬件层面支持

  • 在硬件层面,乘法、除法往往需要额外的硬件模块来支持,其耗费的时钟周期较多。相比之下,移位按位操作都是简单的逻辑运算,现代处理器能够在一个时钟周期内完成。

http://www.mrgr.cn/news/50160.html

相关文章:

  • 【MAUI】步进器
  • Avarra:革新企业销售培训的未来
  • SHA1算法学习
  • Product1M 深度理解 PPT
  • STL.string(上)
  • Linux内核 -- 多核数据同步原语言之 smp_load_acquire 的作用与使用
  • 当下的时代?
  • Kubernetes 节点清空
  • STM32中断
  • JAVA软开-面试经典题(7)-字符串常量池
  • MATLAB代码解析:利用DCGAN实现图像数据的生成
  • 【时间盒子】-【10.自定义弹窗】CustomDialogController
  • 扭亏年只是开始,赛力斯的成长性仍在继续
  • LabVIEW智能可变温循环PCT测试系统
  • micro-memoize 缓存计算结果
  • 一文搞懂进程、线程、协程以及并发、并行、串行的概念
  • 解锁机器学习的新维度:元学习的算法与应用探秘
  • 【随手记】IE和精益的区别
  • CST学习笔记(二)Floquet模式激励设置
  • Java之反射机制详解