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

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

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

相关推荐
寻寻觅觅☆13 小时前
东华OJ-基础题-106-大整数相加(C++)
开发语言·c++·算法
偷吃的耗子14 小时前
【CNN算法理解】:三、AlexNet 训练模块(附代码)
深度学习·算法·cnn
化学在逃硬闯CS14 小时前
Leetcode1382. 将二叉搜索树变平衡
数据结构·算法
ceclar12315 小时前
C++使用format
开发语言·c++·算法
Gofarlic_OMS15 小时前
科学计算领域MATLAB许可证管理工具对比推荐
运维·开发语言·算法·matlab·自动化
夏鹏今天学习了吗15 小时前
【LeetCode热题100(100/100)】数据流的中位数
算法·leetcode·职场和发展
忙什么果16 小时前
上位机、下位机、FPGA、算法放在哪层合适?
算法·fpga开发
董董灿是个攻城狮16 小时前
AI 视觉连载4:YUV 的图像表示
算法
ArturiaZ17 小时前
【day24】
c++·算法·图论
大江东去浪淘尽千古风流人物17 小时前
【SLAM】Hydra-Foundations 层次化空间感知:机器人如何像人类一样理解3D环境
深度学习·算法·3d·机器人·概率论·slam