Ziglings 笔记 97: 位运算的魔法 (XOR Swap)
能够“看见”比特
在 Ziglings 的第 97 个练习中,我们暂时放下了高层的抽象,拿起了手术刀,直接对内存中的二进制位进行操作。
位运算 (Bit Manipulation) 是程序员内功深厚的体现。虽然我们平时写业务逻辑很少用到,但在优化性能、处理硬件协议或编写加密算法时,它就是唯一的语言。
挑战:不使用第三个变量的交换
通常我们交换两个变量需要一个 temp:
const temp = a;
a = b;
b = temp;
但在内存极度受限(如早期的嵌入式设备)或者为了炫技(面试中),我们可能会用到 XOR Swap 算法。题目要求我们补全这个算法。
解决方案
这个算法总是由三步组成:
const std = @import("std");
const print = std.debug.print;
pub fn main() !void {
// 初始值
// x = 1101 (13)
// y = 1011 (11)
var x: u8 = 0b1101;
var y: u8 = 0b1011;
// Step 1: x 变成了 "x 和 y 的差异掩码"
// x = 1101 ^ 1011 = 0110
x ^= y;
// Step 2: y 利用差异掩码变成了原来的 x
// y = 1011 ^ 0110 = 1101 (原 x)
y ^= x;
// Step 3: x 利用差异掩码和新的 y (原 x) 变成了原来的 y
// x = 0110 ^ 1101 = 1011 (原 y)
// 补全这一行:
x ^= y;
print("x = {b}; y = {b}\n", .{ x, y });
}
核心知识点总结
1. XOR 的本质
XOR (异或) 可以被理解为“不进位加法”。
或者更直观地理解为:两次异或同一个数,等于没操作。
- 你有一个值
A。 - 你异或上
K(Key),它变成了加密值E。 - 你再异或一次
K,它又变回了A。 交换算法利用的正是这个“可逆性”。
2. 现代编程建议
虽然 XOR Swap 很酷,但在现代 Zig 编程中,如果你想交换变量,请直接使用 std.mem.swap(T, &a, &b)。
或者就用临时变量 temp。
为什么?
- 可读性:XOR Swap 很难一眼看懂。
- 性能:现代编译器极其聪明。对于
temp写法,编译器通常能直接优化成寄存器重命名或单一的XCHG汇编指令,这比做三次异或运算要快得多。 - 安全性:XOR Swap 有一个致命缺陷——如果
x和y指向同一块内存地址,x ^= x会直接把该地址清零!
3. 位运算的应用场景
除了交换,位运算更多用于:
- 掩码 (Masking):
x & 0x0F(只取低4位)。 - 标志位 (Flags):
flags |= READ_ONLY(设置标志)。 - 紧凑存储: 使用
u1或packed struct来压缩数据。
后续预告:我们已经体验了底层的位运算。接下来的练习通常会进入更实际的系统编程领域,例如处理 Pointers to Pointers 或者更深入的 C Interop 细节。准备好继续深入了吗?