【嵌入式linux学习】0_3位运算整理

位运算整理

最近看到了位运算相关的东西,也趁机会复习一下~

特别是操作寄存器的某些位的时候需要熟练使用 主要就是构建掩码,熟练使用几个运算符~

文章目录


1. 将x的某些位取出来

需求 :从无符号整数 x 中,提取从第 p 位开始(向右数)的 n 位字段。

实现原理

  1. 将目标字段移动到最右侧:执行 x >> (p - n + 1)
  2. 构造掩码(Mask):~(~0 << n) 可以生成一个右起 n 位全为 1,其余为 0 的掩码。
  3. 相与提取:利用 & 运算过滤出目标位。
c 复制代码
unsigned int getbits(unsigned int x, int p, int n) {
    return (x >> (p - n + 1)) & ~(~0 << n);
}

2. 将x的某些位 设置为y的某些位

需求 :将 x 中从第 p 位开始的 n 个位,替换为 y 中最右边的 n 位,其余位保持不变。

实现思路

  • 清理现场 :构造一个 x_mask,将 x 的目标区间清零。
  • 对齐数据 :将 y 的低 n 位移动到第 p 位对齐。
  • 合并结果 :使用按位或 | 运算。
c 复制代码
unsigned int setbits(unsigned int x , int p,int n,unsigned int y){
	unsigned int x_mask=(~((~0)<<n))<<(p-n+1);
    unsigned int y_mask=~((~0)<<n)
    return ((~x_mask)&x) | (y<<(p-n+1) &mask);
}

3. 位翻转:invert 函数

需求 :将 x 中从第 p 位开始的 n 位求反(0 变 1,1 变 0)。

编写一个函数 invert(x, p, n),该函数返回对 x 执行下列操作后的结果值:将 x 中从第 p 位开始的 n 个(二进制)位求反(即,1 变成 0,0 变成 1),x 的其余各位保持不变

核心技巧:异或(XOR)

异或运算 ^ 具有如下神奇特性:

  • any ^ 0 = 保持不变
  • any ^ 1 = 翻转
c 复制代码
unsigned int invert(unsigned int x, int p, int n) {
    // 构造掩码:目标区间为 1,其余为 0
    unsigned int mask = (~(~0u << n)) << (p + 1 - n);
    // 利用异或翻转目标位
    return x ^ mask;
}

4. 循环移位:rightrot 函数

需求:实现循环右移,即从右端移出的位不再丢失,而是从左端重新移入。

编写一个函数 rightrot(x, n),该函数返回将 x 循环右移(即从最右端移出的位将从最左端移入)n(二进制)位后所得到的值

实现步骤

  1. 获取位数 :通过 sizeof(unsigned int) * 8 适配不同系统的字长。
  2. 提取掉落位 :获取即将移出的低 n 位,并将其左移到顶端。
  3. 整体右移:将原数正常右移。
  4. 合并:将"掉落位"与"移位结果"进行或运算。
c 复制代码
unsigned int rightrot(unsigned int x, int n) {
    int wordsize = sizeof(unsigned int) * 8;
    n = n % wordsize; // 处理 n 大于字长的情况
    if (n == 0) return x;

    unsigned int dropped_bits = (x & ~(~0u << n)) << (wordsize - n);
    return (x >> n) | dropped_bits;
}

5. x & (x - 1)

经典技巧,它的核心作用是:消除二进制表示中从右往左数的第一位 1

为什么有效?

当我们执行 x - 1 时:

  • 最右侧的 1 变成 0
  • 该位右侧的所有 0 变成 1
  • 该位左侧保持不变。 此时执行 & 运算,原数中最右侧的 1 及其右边部分都会被抵消。

经典应用:统计 1 的个数

相比于逐位遍历 32 次,该算法的效率取决于 1 的个数。

c 复制代码
int count_ones(unsigned int x) {
    int count = 0;
    while (x > 0) {
        x &= (x - 1); // 每次执行都干掉一个 1
        count++;
    }
    return count;
}

总结

位运算的本质是对**掩码(Mask)移位(Shift)**的灵活组合。

一般用~0 进行位置移动,移动后取反 当作掩码

翻转常用^

相关推荐
0566463 分钟前
Python康复训练——控制流与函数
开发语言·python·学习
easy_coder1 小时前
Linux LVM 知识文档
linux·运维
小小的木头人2 小时前
Ubuntu 使用 udev + systemd + UUID 实现 USB 硬盘自动挂载
linux·运维·ubuntu
早睡早起身体好1232 小时前
为什么 Network 中会出现两个同名请求?——CORS 预检请求学习笔记
网络·笔记·学习·网络安全
菩提树下的打坐2 小时前
测试左移的更深一层:用 DDD 战术设计反推测试边界
学习
casual~3 小时前
模逆元计算方法详解:扩展欧几里得算法与费马小定理
学习·算法·逆元
@Mike@3 小时前
06-数据库学习笔记(存储模型与数据压缩)
数据库·笔记·学习
kaoa0003 小时前
Linux入门攻坚——84、网络虚拟化技术-1
linux·运维·服务器
RisunJan3 小时前
Linux命令-shutdown(安全关闭或重启系统)
linux·服务器·安全
我的xiaodoujiao4 小时前
快速学习Python基础知识详细图文教程14--模块
开发语言·python·学习·测试工具