Ziglings 笔记 40: 只读指针 (*const)
我只看看,不进去
在 Ziglings 的第 40 个练习中,我们遇到了指针与 const 的纠葛。
在 C 语言中,const int * 和 int * const 经常把初学者绕晕。Zig 的语法则更加直观。
挑战:类型不匹配
代码试图定义一个指针 b 指向变量 a。
虽然如果 a 是 var,普通的 *u8 指针是合法的;但这个练习的核心在于理解:如果数据是常量的,或者我们希望它是只读的,指针类型必须做出改变。
Zig 编译器非常严格:你不能创建一个“可变指针”去指向一个“常量数据”。
解决方案
为了最安全地引用数据(或者如果 a 是 const),我们需要将指针类型声明为 *const u8:
const std = @import("std");
pub fn main() void {
// 原始数据可以是 var (可变) 或 const (不可变)
var a: u8 = 12;
// 修复点:显式声明为 *const u8
// 含义:b 是一个指针,它指向的内容是不可修改的 (const u8)
// 即使 a 本身是 var,b 也只能“读”不能“写”。
const b: *const u8 = &a;
// b.* = 20; // 如果尝试这行代码,编译器会报错,因为 b 认为是只读的。
std.debug.print("a: {}, b: {}\n", .{ a, b.* });
}
核心知识点总结
1. 指针类型解剖
*u8: 读写指针。只能指向var变量。*const u8: 只读指针。可以指向const变量,也可以指向var变量(降级权限)。
2. 权限流向
Zig 允许你放弃写入权限,但不允许你凭空捏造写入权限。
- ✅
var->*const T(安全:我承诺不改) - ❌
const->*T(危险:我试图修改常量)
3. API 设计
在设计函数参数时,这非常有用。
如果你的函数只是读取数据,参数应该写成 input: *const u8。这样调用者既可以传常量指针,也可以传变量指针,而且调用者知道:“放心,这个函数不会修改我的数据”。
后续预告:我们已经学会了指向单个变量的指针。但在 C 语言中,指针和数组是不分家的。在 Zig 中,我们有更好的工具——多项指针 (Many-item Pointers) 和切片。下一篇将是一个挑战!