嵌入式算法——位运算专题

在嵌入式开发中,外设(GPIO、UART、ADC、定时器等)通常通过内存映射的寄存器控制。这些寄存器的每一位或几位代表特定功能(如使能、方向、中断标志等),不用位运算,就无法精确控制某一位而不影响其他位。

例如:从一个 16 位传感器数据中提取高 4 位作为类型,低 12 位作为值:

cpp 复制代码
uint16_t data = read_sensor();
uint8_t type = (data >> 12) & 0x0F;    // 高4位
uint16_t value = data & 0x0FFF;        // 低12位

又或者,设置 GPIOA 的第 5 位为输出高电平

cpp 复制代码
GPIOA->ODR |= (1 << 5);   // 置位:输出高
GPIOA->ODR &= ~(1 << 5);  // 清零:输出低

C/C++ 中常用的位运算符:

运算符 名称 说明 示例(a=5, b=3)
& 按位与 对应位都为1,结果为1 5 & 3 = 1 (0101 & 0011 = 0001)
` ` 按位或 对应位有一个为1,结果为1
^ 按位异或 对应位不同为1 5 ^ 3 = 6 (0101 ^ 0011 = 0110)
~ 按位取反 0变1,1变0 ~5(假设8位)= 11111010 = -6(补码)
<< 左移 各位左移,低位补0 5 << 1 = 10 (0101 → 1010)
>> 右移 逻辑右移(无符号)或算术右移(有符号) 5 >> 1 = 2 (0101 → 0010)

常用位运算技巧

置位(Set bit):reg |= (1 << n); // 将 reg 的第 n 位置 1

清零(Clear bit):reg &= ~(1 << n); // 将 reg 的第 n 位清 0

翻转(Toggle bit):reg ^= (1 << n); // 第 n 位 0→1,1→0

判断某位是否为1:if (reg & (1 << n)) { }

提取连续几位:uint8_t field = (reg >> 2) & 0x07; // 0x07 = 0b111,提取 bits [4:2](共3位)

力扣中对应题目

二进制枚举类问题:78. 子集 - 力扣(LeetCode)

cpp 复制代码
class Solution {
public:

    // 位运算,从0000-1111一直遍历所有情况
    vector<vector<int>> subsets(vector<int>& a) {
        vector<vector<int>> result;
        int n = a.size();
        int maxstate = 1 << n;
        for(int s = 0; s < maxstate; s++) {
            vector<int> tmp;
            for(int i = 0; i < n; i++) {
                int b  = (s >> i) & 1;  // 提取s的第i位
                if(b) tmp.push_back(a[i]);
            }
            result.push_back(tmp);
        }
        return result;

    }
};

lowbit类问题:191. 位1的个数 - 力扣(LeetCode)

cpp 复制代码
class Solution {
public:
    // 常规方法
    // int hammingWeight(int n) {
    //     int cnt = 0;
    //     for(int i = 0; i < 32; i++) {
    //         if((n >> i) & 1) cnt++;
    //     }
    //     return cnt;
    // }

    // lowbit 方法
    int hammingWeight(int n) {
        int cnt = 0;
        while(n) {
            int lowbit = n & (-n);
            cnt++;
            n -= lowbit;
        }
        return cnt;
    }
};

数位问题:137. 只出现一次的数字 II - 力扣(LeetCode)

cpp 复制代码
class Solution {
public:
    int singleNumber(vector<int>& nums) {
        int res = 0;
        for(int i = 0; i < 32; i++) {
            int cnt = 0;
            for(int x : nums) {
                int bit = (x >> i) & 1;
                if(bit) cnt++;
            }
            if(cnt % 3) res |= 1 << i; 
        }

        return res;
    }
};

201. 数字范围按位与 - 力扣(LeetCode)

cpp 复制代码
class Solution {
public:
    int rangeBitwiseAnd(int left, int right) {
        int ret = 0;
        for(int i = 30; i >= 0; i--) { // 从最高位开始遍历
            int bl = (left >> i) & 1;  // l的第i位
            int br = (right >> i) & 1;  //  第i位
            if(bl && br) ret |= 1 << i; // 1 1 - res这位也为1
            else if(!bl && br) break; // 0 1 - 这位后面都是0
        }
        return ret;
    }
};

异或技巧类问题:136. 只出现一次的数字 - 力扣(LeetCode)

cpp 复制代码
class Solution {
public:
    int singleNumber(vector<int>& nums) {
        int result = 0;
        for(int i = 0; i < nums.size(); i++){
            result ^= nums[i];
        }
        return result;
    }
};

上面五道题是位运算基础题,也是笔面试常考题,更深入的位运算题目可自行了解。

相关推荐
CoovallyAIHub9 小时前
Moonshine:比 Whisper 快 100 倍的端侧语音识别神器,Star 6.6K!
深度学习·算法·计算机视觉
CoovallyAIHub10 小时前
速度暴涨10倍、成本暴降6倍!Mercury 2用扩散取代自回归,重新定义LLM推理速度
深度学习·算法·计算机视觉
CoovallyAIHub10 小时前
实时视觉AI智能体框架来了!Vision Agents 狂揽7K Star,延迟低至30ms,YOLO+Gemini实时联动!
算法·架构·github
CoovallyAIHub10 小时前
开源:YOLO最强对手?D-FINE目标检测与实例分割框架深度解析
人工智能·算法·github
CoovallyAIHub11 小时前
OpenClaw:从“19万星标”到“行业封杀”,这只“赛博龙虾”究竟触动了谁的神经?
算法·架构·github
刀法如飞11 小时前
程序员必须知道的核心算法思想
算法·编程开发·算法思想
徐小夕12 小时前
pxcharts Ultra V2.3更新:多维表一键导出 PDF,渲染兼容性拉满!
vue.js·算法·github
CoovallyAIHub13 小时前
OpenClaw一脚踩碎传统CV?机器终于不再只是看世界
深度学习·算法·计算机视觉
CoovallyAIHub13 小时前
仅凭单目相机实现3D锥桶定位?UNet-RKNet破解自动驾驶锥桶检测难题
深度学习·算法·计算机视觉
zone773913 小时前
002:RAG 入门-LangChain 读取文本
后端·算法·面试