Ziglings 笔记 39: 指针初探
内存的地图
在 Ziglings 的第 39 个练习中,我们终于触碰到了系统编程的灵魂:指针 (Pointers)。
对于很多从高级语言(如 Python/JS)转来的同学,指针听起来很可怕。但在 Zig 中,指针只是一个指向某个值的“引用”或“地址”。可以将它想象成一个路牌,上面写着你要找的数据住在哪里。
挑战:隔空取物
我们有一个变量 num1,它的值为 5。
我们要通过一个指向 num1 的指针,把这个 5 赋值给 num2。
解决方案
这是使用 Zig 指针语法的实现:
const std = @import("std");
pub fn main() void {
var num1: u8 = 5;
// 1. 获取地址 (&)
// &num1 取出了 num1 在内存中的地址
// 类型 *u8 表示 "指向 u8 的单项指针"
const num1_pointer: *u8 = &num1;
var num2: u8 = undefined;
// 2. 解引用 (.*)
// num1_pointer 是地址,num1_pointer.* 是地址里住着的值
// 我们把这个值(5) 复制给了 num2
num2 = num1_pointer.*;
std.debug.print("num1: {}, num2: {}\n", .{ num1, num2 });
}
核心知识点总结
1. 语法速查表
| 操作 | Zig 语法 | C 语言语法 | 含义 |
|---|---|---|---|
| 定义类型 | *u8 | uint8_t * | 指向 u8 的指针类型 |
| 取地址 | &foo | &foo | 获取 foo 的内存地址 |
| 解引用 | ptr.* | *ptr | 获取指针指向的值 |
2. 为什么是后缀 .*?
这是 Zig 的一大特色。在 C 语言中,解引用是前缀操作符 *ptr。但在 Zig 中,为了让代码读起来更顺畅(从左到右),解引用被设计为后缀 ptr.*。
这避免了 C 语言中复杂的优先级问题(比如 *ptr.field 到底是先解引用还是先访问字段?),让代码逻辑更加线性。
3. 安全性
Zig 的指针比 C 语言安全得多:
- 不能是
null(除非你显式使用?*T)。 - 不能像整数一样随意加减(防止指到非法内存)。
- 必须指向合法的内存(不允许野指针)。
后续预告:既然我们已经能用指针指向单个变量,那能不能让指针修改变量的值呢?下一篇我们将深入探讨指针的可变性。