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

翻转常用^

相关推荐
企鹅侠客15 小时前
Linux CPU 负载平均值(Load Average)详解:从原理到实践
linux·运维·服务器·服务器负载
adinnet202615 小时前
电商客服对话知识库的自学习闭环与质量演进机制
学习
易点云徐源15 小时前
HP 暗影精灵 PRO 16 安装双系统后,开机直接进入 Windows,按 F9 才能进入 Ubuntu:GRUB 菜单不显示的处理方法
linux·运维·ubuntu
第404号工位16 小时前
离职退电脑前别只点“清空回收站”!手把手教你彻底抹除凭证与数字痕迹
linux·python·架构
lazy H16 小时前
【计算机网络】第 13 篇:NAT 和端口映射是什么?为什么本地服务外网访问不了?
java·网络·网络协议·学习·计算机网络·408
就像楞次定律16 小时前
【Linux 学习记之二】C++ 构建体系与底层链接机制的深度透视(1)
linux·后端
米优16 小时前
linux下获取崩溃程序的core文件
linux·运维·服务器
qeen8716 小时前
【Linux】动静态库的制作使用及ELF文件的宏观理解
linux·运维·库
试剂界的爱马仕17 小时前
α-Cyano-4-hydroxycinnamic acid(CHCA)用作 MALDI-TOF 基质的配制与使用
大数据·人工智能·深度学习·学习
YYRAN_ZZU17 小时前
FlameGraph 火焰图介绍和使用
linux·嵌入式硬件