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

翻转常用^

相关推荐
Shell运维手记10 小时前
Linux (挂载|rpm|yum|源码编译)
linux·运维·笔记·网络协议·bash
RisunJan11 小时前
Linux命令-vgchange(修改 LVM 卷组属性)
linux·运维·服务器
ZMacros11 小时前
Buildroot构建文件系统
linux·服务器
深念Y11 小时前
AI Agent 时代运维安全:rm 防误删方案对比
linux·运维·人工智能·安全·自动化·agent
hkNaruto11 小时前
【Linux】Ubuntu 22.04 LTS GNOME 原生远程桌面配置:告别vnc、nomachine
linux·运维·ubuntu
wuhuhuan12 小时前
【JMeter 学习打卡 Day 4】多用户登录 + 动态 token 关联
学习·jmeter
崇子嵘12 小时前
基于zynqMPsoc15eg的linux端axi dma教训总结
linux·运维·服务器
动力 continue12 小时前
Linux 基础篇 · Vim 三种模式与常用指令
linux·运维·vim
Code额13 小时前
Python asyncio 异步编程全套学习文档(零基础完整版)
python·学习·oracle·async·异步·asyncio
深念Y13 小时前
系统内存与Swap优化记录
linux·内存·优化·虚拟内存·压缩·ram·zram