嵌入式学习日志——C语言(十二)
/ ~(1<<n)生成“第n位为0,其余为1”的掩码,与num按位与后第n位必为0。// 1<<n生成“第n位为1,其余为0”的掩码,与num按位或后第n位必为1。// 右移n位后与1按位与,结果为1则该位是1,否则为0。b = a ^ b;// 等价于 b = (a^b)^b = a(消去b)// 等价于 a = (a^b)^a = b(消去a)- 有符号数:左侧补符号位(正数补 0,负数补 1
11 学习位运算
1 位运算符(操作二进制位的基本工具)
1.1 运算符分类及功能
|
运算符 |
功能 |
运算规则 |
补充说明 |
|
|---|---|---|---|---|
|
|
按位与 |
对应位都为 1 时,结果为 1;否则为 0 |
可用于 “保留指定位”“清零指定位” |
|
|
` |
` |
按位或 |
对应位至少有 1 个为 1 时,结果为 1 |
可用于 “设置指定位为 1” |
|
|
按位异或 |
对应位不同为 1,相同为 0 |
可用于 “翻转指定位”“交换变量” |
|
|
|
按位取反 |
0 变 1,1 变 0 |
单目运算符,结果与原数符号相反 |
|
|
|
左移 |
二进制位整体左移,右侧补 0 |
相当于 “乘以 2ⁿ”(不溢出时) |
|
|
|
右移 |
分两种情况: |
正数右移相当于 “除以 2ⁿ”(向下取整) |
1.2 特殊应用详解
-
按位异或交换两个数:
a = a ^ b;
b = a ^ b; // 等价于 b = (a^b)^b = a(消去b)
a = a ^ b; // 等价于 a = (a^b)^a = b(消去a)
优势:不占用额外空间(无需临时变量)
注意:若a和b指向同一块内存(如a与a交换),结果会变为 0,需避免这种场景
1.3 优先级规则(从高到低)
~(取反) →<</>>(移位) →&(按位与) →^(按位异或) →|(按位或)
a | b & c等价于a | (b & c)(先算&)
~a << 2等价于(~a) << 2(先算~)
1.4 位操作典型场景(核心应用)
1、置位操作(设置指定位为 1)
将num的第n位(从 0 开始计数,最低位为第 0 位)设为 1:
num |= (1 << n); // 1<<n生成“第n位为1,其余为0”的掩码,与num按位或后第n位必为1
例:将num=5(101)的第 1 位设为 1 → 5 | (1<<1) = 5 | 2 = 7(111)
2、清零操作(设置指定位为 0)
将num的第n位设为 0:
num &= ~(1 << n); // ~(1<<n)生成“第n位为0,其余为1”的掩码,与num按位与后第n位必为0
例:将num=7(111)的第 1 位设为 0 → 7 & ~2 = 7 & 5 = 5(101)
3、取指定位的值
判断num的第n位是 0 还是 1:
int bit = (num >> n) & 1; // 右移n位后与1按位与,结果为1则该位是1,否则为0
2 位运算示例(基于 32 位有符号整数)
2.1 按位与(&)
num = 9 & 6;
9 的二进制:
0000 0000 0000 0000 0000 0000 0000 10016 的二进制:
0000 0000 0000 0000 0000 0000 0000 0110按位与结果:
0000 0000 0000 0000 0000 0000 0000 0000→num = 0
2.2 按位或(|)
num = 9 | 6;
9 的二进制:
... 10016 的二进制:
... 0110按位或结果:
... 1111→ 十进制 15 →num = 15
2.3 按位异或(^)
num = 9 ^ 5;(替换原示例,避免与|结果巧合一致)
9 的二进制:
... 10015 的二进制:
... 0101按位异或结果:
... 1100→ 十进制 12 →num = 12
2.4 左移(<<)
num = 9 << 3;
9 的二进制:
... 1001左移 3 位:
... 1001 000(右侧补 0) → 十进制 72 →num = 72注意:若左移导致溢出(如 32 位 int 的
1 << 31会变成负数),结果不再等于 “乘以 2ⁿ”
2.5 右移(>>)
正数右移:
num = 9 >> 3;
9 的二进制:... 1001→ 右移 3 位:... 0001(补 0) →num = 1(9÷8=1.125,向下取整)负数右移(算术右移):
num = -9 >> 3;
-9 的补码:1111 ... 1111 0111→ 右移 3 位(补 1):1111 ... 1111 1110→ 十进制 - 2(与 - 9÷8=-1.125 的取整结果不同,需注意)
2.6 按位取反(~)
num = ~9;
9 的补码:
0000 ... 0000 1001取反后补码:
1111 ... 1111 0110(负数)转原码:符号位不变,其余位取反加 1 →
1000 ... 0000 1010→ 十进制 - 10 →num = -10
3 关键补充说明
3.1 位运算 vs 逻辑运算
|
类型 |
操作对象 |
结果范围 |
示例对比(a=3 即 11,b=5 即 101) |
||
|---|---|---|---|---|---|
|
位运算 |
二进制位(逐位) |
与操作数同类型 |
|
b = 7`(111) |
|
|
逻辑运算 |
整体真假(0 为假,非 0 为真) |
0 或 1(int) |
|
b = 1` |
3.2 效率与适用场景
-
效率:位运算(如
<</>>)比乘除运算快,因硬件直接支持二进制移位 -
典型场景:
-
底层硬件控制(寄存器位操作)
-
状态标志位(用 1 位表示一个开关状态,节省内存)
-
权限控制(如用 8 位二进制表示 8 种权限)
-
数据压缩 / 加密(基于位的算法)
-
奇偶校验(
num & 1判断奇偶:结果为 1 是奇数,0 是偶数)
-
3.3 常见误区
-
位数计数从 0 开始(最低位是第 0 位,非第 1 位)
-
右移对负数的处理与除法不同(算术右移可能导致结果偏差)
-
异或交换变量并非绝对安全(同地址变量会出错)
-
左移可能导致符号位变化(有符号数溢出后结果不可控)
openvela 操作系统专为 AIoT 领域量身定制,以轻量化、标准兼容、安全性和高度可扩展性为核心特点。openvela 以其卓越的技术优势,已成为众多物联网设备和 AI 硬件的技术首选,涵盖了智能手表、运动手环、智能音箱、耳机、智能家居设备以及机器人等多个领域。
更多推荐


所有评论(0)