1. 位运算基础
各位同学,欢迎来到《位运算技巧与协议解析实战》的第一章。
说实话,我做了十几年嵌入式开发,跟各种协议、寄存器打了无数交道。回头一看,最基础的东西往往最容易被忽视。位运算就是这样的存在——你越懂它,写出来的代码就越优雅、越高效。
1.1 二进制:计算机的母语
计算机只认0和1。这不是什么新鲜事,但你真的理解二进制吗?
我见过不少工程师,写代码时习惯用十进制思考。比如设置一个寄存器,直接写 0x3F 就完事了。但遇到需要只改某一位的情况,就傻眼了。
二进制数,说白了就是逢二进一。每一位的权重是2的幂次方:
二进制: 1 0 1 1
权重: 8 4 2 1
计算: 8 + 0 + 2 + 1 = 11 (十进制)
核心要点:二进制每一位只有0或1,对应电路里的「开」和「关」。这就是为什么位运算如此高效——它直接操作硬件逻辑。
1.2 十六进制:工程师的速记法
二进制写起来太长了。一个32位的数,写出来32个0和1,谁受得了?
十六进制就是为此而生。4位二进制对应1位十六进制,简洁又直观。
| 二进制 | 十六进制 | 十进制 |
|---|---|---|
| 0000 | 0 | 0 |
| 0001 | 1 | 1 |
| 1010 | A | 10 |
| 1111 | F | 15 |
我个人习惯,在代码里看到 0xAB,脑子里立刻反应出 1010 1011。这需要练习,但一旦熟练了,读协议文档就像看母语一样快。
小技巧:调试时把变量打印成十六进制,比十进制更容易看出位模式。我在调试I2C协议时,经常用 printf("0x%02X", data) 来观察数据。
1.3 原码、反码、补码:负数的三种面孔
为什么计算机要用补码?这个问题我当年也困惑过。
先看原码:最高位表示符号,0正1负。比如 0000 0011 是3,1000 0011 是-3。
反码:正数不变,负数除了符号位外全部取反。
补码:正数不变,负数在反码基础上加1。
举个例子,用8位表示:
数字: +3
原码: 0000 0011
反码: 0000 0011
补码: 0000 0011
数字: -3
原码: 1000 0011
反码: 1111 1100
补码: 1111 1101
为什么会这样?你想想看,如果直接用原码做加法,3 + (-3) 会得到 0000 0110,也就是6,这显然不对。
补码的好处是:加法和减法可以用同一套电路。 3 + (-3) 用补码算:0000 0011 + 1111 1101 = 1 0000 0000,溢出后正好是0。
注意:我曾经在写一个传感器驱动时,因为没注意补码转换,读出来的温度值总是差几度。查了半天才发现是负数解析错了。嗯,这里要特别小心——有符号数的右移操作,不同编译器行为可能不一样。
1.4 与、或、非、异或:位运算四剑客
这四个运算,是位操作的基本功。我几乎每天都在用。
按位与(&)
两个位都是1,结果才是1。常用于清零或提取特定位。
1010 1101
& 0000 1111
-----------
0000 1101 // 只保留低4位
我在项目中遇到过:需要读取一个寄存器的低3位,其他位忽略。一行 value & 0x07 搞定。
按位或(|)
只要有一个是1,结果就是1。常用于置位。
1010 1101
| 0000 0011
-----------
1010 1111 // 低2位置1
按位非(~)
0变1,1变0。注意这是单目运算符。
~ 1010 1101
-----------
0101 0010
我建议你小心使用 ~,尤其是在有符号数上。比如 ~0 在32位系统上是 0xFFFFFFFF,也就是-1。
按位异或(^)
相同为0,不同为1。这个运算特别有意思。
1010 1101
^ 0000 1111
-----------
1010 0010 // 低4位取反
异或有个经典用法:交换两个变量,不用临时变量。
a = a ^ b;
b = a ^ b;
a = a ^ b;
不过说实话,现在编译器优化得很好,这种写法更多是为了炫技。我一般只在加密算法里大量使用异或。
实战口诀:
- 想清零某几位?用 & 配合掩码
- 想置位某几位?用 | 配合掩码
- 想翻转某几位?用 ^ 配合掩码
- 想取反所有位?用 ~
知识体系总览
下面这张图,是我梳理的本章知识结构。你可以把它当作一个思维导图来看:
这张图把本章的知识点串起来了。你从中心往外看,二进制是基础,十六进制是工具,原反补是理解负数的关键,而四个基本运算就是你的武器。
我的建议:刚开始学的时候,拿一张纸,自己写几个二进制数,手动算一遍与或非异或。别嫌麻烦。我当年就是这么练的,后来看协议文档里的位域定义,一眼就能看出该怎么操作。
好了,这一章就到这里。记住:位运算不是冷冰冰的数学,它是你和硬件对话的语言。掌握了它,你写驱动、调协议、优化性能,都会顺手很多。
可可精品资料库