【嵌入式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 进行位置移动,移动后取反 当作掩码

翻转常用^

相关推荐
悲伤小伞2 小时前
9-MySQL_索引
linux·数据库·c++·mysql·centos
SeanDe2 小时前
【Linux `top` 命令详解(结合截图逐行拆解)】
linux·运维·服务器
mi20062 小时前
wiki.js知识库系统搭建和配置总结
linux·运维·知识库
向依阳2 小时前
Linux应用-----进程间通信
linux
hssfscv2 小时前
软件设计师下午题二 E-R图
java·笔记·学习
桌面运维家2 小时前
Windows/Linux文件访问权限修改指南
linux·运维·服务器
badhope2 小时前
Docker入门到实战全攻略
linux·python·docker·github·matplotlib
麦芽糖02192 小时前
centos虚拟机忘记密码怎么办
linux·运维·centos
RSFeegg3 小时前
【AI Agent 学习笔记task2】Day3 Hello-Agents 第二章:智能体发展史深度解读
人工智能·笔记·学习