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

在嵌入式开发中,外设(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;
    }
};

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

相关推荐
智驱力人工智能21 小时前
馆藏文物预防性保护依赖的图像分析技术 文物损害检测 文物破损检测 文物损害识别误报率优化方案 文物安全巡查AI系统案例 智慧文保AI监测
人工智能·算法·安全·yolo·边缘计算
wuguan_21 小时前
Halcon中值滤波,均值滤波,高斯滤波
算法·halcon
☆56621 小时前
C++安全编程指南
开发语言·c++·算法
tobias.b21 小时前
机器学习 超清晰通俗讲解 + 核心算法全解(深度+易懂版)
人工智能·算法·机器学习
budingxiaomoli1 天前
优选算法--bfs解决FloodFill问题
算法·宽度优先
超级大只老咪1 天前
贪心算法对应策略
算法·贪心算法
im_AMBER1 天前
Leetcode 145 回文数 | 加一
数据结构·算法·leetcode
2501_945424801 天前
C++构建缓存加速
开发语言·c++·算法
2401_851272991 天前
多平台UI框架C++开发
开发语言·c++·算法
m0_518019481 天前
C++中的命令模式实战
开发语言·c++·算法