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 语言语法含义
定义类型*u8uint8_t *指向 u8 的指针类型
取地址&foo&foo获取 foo 的内存地址
解引用ptr.**ptr获取指针指向的值

2. 为什么是后缀 .*

这是 Zig 的一大特色。在 C 语言中,解引用是前缀操作符 *ptr。但在 Zig 中,为了让代码读起来更顺畅(从左到右),解引用被设计为后缀 ptr.*。 这避免了 C 语言中复杂的优先级问题(比如 *ptr.field 到底是先解引用还是先访问字段?),让代码逻辑更加线性。

3. 安全性

Zig 的指针比 C 语言安全得多:

  • 不能是 null(除非你显式使用 ?*T)。
  • 不能像整数一样随意加减(防止指到非法内存)。
  • 必须指向合法的内存(不允许野指针)。

后续预告:既然我们已经能用指针指向单个变量,那能不能让指针修改变量的值呢?下一篇我们将深入探讨指针的可变性。