指针全家桶 — 一个还是多个?长度谁知道?四种类型答两个问题
指针全家桶 — 一个还是多个?长度谁知道?四种类型答两个问题
这一章讲什么: 2.2 节是全书机制密度最高的一节。它把「指针」这个 C 里 一个星号打天下的概念,拆成按两个问题分类的一张类型网: 指向一个还是多个?长度在编译期知道还是运行期知道? 两个问题答完,Zig 用来表达内存的类型就全部有了着落: 单元素指针、多元素指针、数组、slice,再加上字符串和缓冲区这两个 「天天见、必须拆穿」的特例。 读完你会看懂 Zig 代码里每一颗星号和每一对方括号。
1. 这一章讲什么
作者开场交了底:指针是他写系统代码时最爱的部分——学会「不把程序搞得 面目全非地 wield(驾驭)指针」之后,它们给的力量、灵活性和控制力 是高层抽象给不了的1。Zig 用的是裸机器指针(raw machine pointer)2。
同时也把丑话说在前面:指针说到底只是内存地址——「代表进程内存里 某个具体位置的数」3。这意味着你可以读到没初始化的内存、访问已经 失效的数据,或者撞上那个所有系统程序员的噩梦:segfault—— 程序试图访问操作系统没有许可它用的内存地址时的崩溃4。 作者还补了一刀私人观察:按他的大学经验,segfault 完全可以被准确描述为 「一种本科生刑具」5。
Zig 的做法不是消灭这些风险(那要把指针变成别的东西), 而是给每种风险配一个看得见的类型。
2. 顶层全景:两个问题一张网
问 ①:这个指针指向「一个」东西,还是「一串」东西?
│
├─ 一个 → *T(单元素指针)
│
└─ 一串 → 问 ②:这一串有多长?谁知道?
│
├─ 编译期就知道,就写在类型里 → [N]T(数组)
├─ 运行期才知道 → []T(slice:指针 + 长度)
└─ 压根没人知道,程序员自己记着 → [*]T(多元素指针)
图说:Zig 的五种内存类型(连数组带指针)全部落在这张二分树上。
C 把这整张树压成一个 char*;Zig 把每一枝都立成独立的类型。这张树就是全章的地图。下面沿着它走,每个叶子一节。
3. 核心原理
3.1 单元素指针:*T —— 一个地址,带着可变性
写法和读法。 单元素指针(single-item pointer)装着一个元素在内存里的地址,
类型写法是星号加目标类型:*i32、*bool6。在 comptime 的账本上,
* 是个一元运算符(和负号 - 同类):吃一个类型 T,吐出「指向 T 的单元素指针」
这个类型7。对人来说读法很顺:从左往右读,像读英语句子8。
取地址与解引用。 &x 取 x 的地址;x_ptr.* 解引用——取出那个地址里
装的东西(. 加 *,刻意和成员访问的点语法对称)9。
var x: i32 = 123;
const x_ptr: *i32 = &x; // x_ptr 存的是 x 的地址
x_ptr.* = 456; // 通过地址,把 x 改成 456
// 现在 x 和 x_ptr.* 都是 456可变性长在指针类型上。 指针「继承」它所指数据的可变性,而继承的结果 写进类型:
var a: i32 = 123;
const b: i32 = 456;
const a_ptr = &a; // 类型:*i32 —— 指向可改的数据
const b_ptr = &b; // 类型:*const i32 —— 指向不可改的数据(常指针)
a_ptr.* = 25; // 合法
b_ptr.* = 50; // 编译错误:cannot assign to constant原书让你猜编译器说什么——答案是 error: cannot assign to constant,
指出 b_ptr.* = 50; 那一行10。因为 b_ptr 是指向常量的指针
(constant pointer),通过它写入是非法的,编译器当场抓住11。
窄化:安全方向的自动转换。 「常指针是可变指针的更窄(narrower)类型」——
窄(narrow)的意思是约束更多12。所以把 *i32 赋给 *const i32
是合法的自动转换(coerce)——收窄永远安全,放宽不行13。
这条规则有个很实用的读法(原书点出):看一个函数的参数,
如果它收的是 *const T,你就知道这个函数不打算改你的数据;
收 *T 才需要警惕。指针的 const 性成了函数签名里的说明书14。
野外的用途:写「操纵数据的函数」、在数据结构里存引用、 以及和 C API 打交道时的 out parameter(通过指针往外写数据的参数)15。
3.2 数组:[N]T —— 是值,不是引用
一个会咬人的差异。 作者自述:他最初在 Zig 里用数组的经历堪称 「困惑与扑腾」——数组这么简单的东西,怎么可能和别的语言不一样?16 答案就一句:Zig 的数组是值,不是引用17。
这句话的工程后果,用主线例子看最清楚:
const arr = [3]i32{ 1, 2, 3 }; // 一个数组值
var arr_copy = arr; // 拷贝 —— 整个数组被复制了一份!
arr_copy[2] = 5; // 改拷贝的第三个元素
std.debug.print("arr: {any}\n", .{arr});
std.debug.print("arr_copy: {any}\n", .{arr_copy}); 内存里真实发生的事:
arr → [ 1, 2, 3 ] 原地不动
arr_copy → [ 1, 2, 5 ] 另一份完整的拷贝
输出:arr: { 1, 2, 3 } arr_copy: { 1, 2, 5 }
图说:拷贝数组 = 拷贝全部元素,不是拷贝一个「指向同一份数据的句柄」。
这是「数组是值」的直接后果,数字是程序真实输出。对比 JavaScript/Java 里 b = a 后两个名字指向同一个数组、
改 b[2] 连 a 一起变——Zig 里那种事不会发生,除非你显式用指针。
在 Zig 里,拷贝一个数组类型的变量,拷的就是整个数组18。
两个连带规则。 第一,下标从 0 开始:0 是第一个,1 是第二个19。
第二,数组的 const 性就是元素的 const 性——const 数组的元素不能改,
所以要改拷贝,arr_copy 必须声明成 var20。
类型的形状。 数组类型写作 [N]T:N 是元素个数,T 是元素类型21。
初始化时如果嫌「先数个数再列元素」重复,可以用下划线让编译器替你数:
[_]i32{ 1, 2, 3 } 仍然是 [3]i3222。
那函数想改数组怎么办? 按值传参会拷整个数组。两个办法:
传「指向数组的单元素指针」*[N]T(不想被改就传 *const [N]T)23。
但这仍解决不了根本问题——长度必须写死在类型里,
一个只能吃 [3]i32 的函数没法吃 [5]i32。要写出「任何长度都收」的函数,
需要本章主角:slice。
3.3 slice:[]T —— 指针加长度的「带超能力的多元素指针」
定义。 slice 是**「指向多个元素的指针 + 一个长度」**24。
类型写作 []T(元素类型 T);同样有 const 版 []const T25。
它可以像数组一样按下标读写,但骨子里仍是指针——数据永远在别处。
怎么来的。 slice 可以从「指向数组的单元素指针」自动转换过来:
*[N]T 指向一串元素、长度编译期已知,转成 slice 时指针指向数组开头,
长度取整个数组26。
主线例子接上: 上一节的数组继续往下走——
const arr = [_]i32{ 11, 22, 33, 44, 55 }; // [5]i32
const slice: []const i32 = &arr; // 转成 slice:ptr 指向 11,len 是 5
const x = slice[2]; // x = 33
std.debug.print("slice: {any}, x: {}\n", .{slice, x});
std.debug.print("ptr: {*}, len: {}\n", .{slice.ptr, slice.len}); 每步旁边的具体状态:
arr [11, 22, 33, 44, 55] 数组值本身
&arr *[5]i32 指向整个数组
slice ptr → 11 的起始地址 slice 的两个字段
len = 5
slice[2] 33 按下标读(0 起)
输出 slice: { 11, 22, 33, 44, 55 }, x: 33
ptr: i32@10217d4, len: 5
(地址原书印的是示例机的;你的机器上会不一样)
图说:slice 的全部家当就是两个字段:一个地址、一个长度。
数字(除标注的地址外)都是程序真实输出。ptr 和 len 两个字段可以用点语法直接看;len 的类型是 usize—— 和第 04 篇「usize 专管下标和长度」对上了;ptr 的类型是个新面孔: 多元素指针27。
越界检查:slice 与裸指针的第一个分水岭。 安全模式下, 访问 slice 越界的下标会看到错误和栈回溯28—— 因为 len 在手里,编译器生成的检查是办得到的。 C 的数组退化成指针之后,这个检查就没了,这就是为什么 C 的越界是 「未定义行为」而 Zig 里是「当场抓住」。
多元素指针:[*]T —— 数不知道的裸指针。 类型写作 [*]T 或 [*]const T,
代表「某一些元素的地址」——编译器不知道有多少个,程序员自己记账29。
它和 slice 一样可以按下标、可以切片;区别只是不替你存长度。
原书给的定位很准:slice 像是有超能力的多元素指针——
安全检查好用,len 随取随用;只有当你刻意不想存长度
(比如优化数据结构)时,才退回裸的多元素指针30。
另外,C 代码满世界用指针表示「一串东西」,和 C 集成时,
多元素指针能表达 C 表达不了的语义31。
切一刀:范围运算符 .. 有时不想要整串,要其中一段。范围运算符是两个点 ..,
arr[1..4] 的意思是从下标 1 开始、到下标 4 为止(不含 4)32:
arr[1..4] → { 22, 33, 44 } 左闭右开,长度 4 - 1 = 3从数组上取范围,结果永远是一个 slice——这个操作就叫 slicing(切片);
slice 还能再切 slice33。到这里,「写一个对任意长度数据都成立的函数」
终于可能了:参数写 []const T,里面只管按下标和 len 操作,
数据在栈上、在堆上、在内存的哪个角落,都无所谓。
slice 是 Zig 里最重要的数据类型,没有之一——标准库半壁江山都收它。
3.4 缓冲区与 undefined:显式的「我没初始化」
缓冲区(buffer) 就是暂存数据的地方34——本章开头 hello world 里
那个 1024 字节的 stdout_buffer 就是。很多 Zig 函数的要求是:
你(调用方)把缓冲区作为参数递进来,通常的形态是 []u8
(一个可变字节 slice)。
怎么造一个空的? 声明一个数组,然后不给初值——但「不给初值」
在 Zig 里也必须显式写出来,特殊值就叫 undefined:
var stdout_buffer: [1024]u8 = undefined;undefined 的规矩。 它是「这个变量现在没有有效值」的显式声明, 代价由你承担:读了没写的 undefined 内存,结果不可预测,后果可以很严重—— 原书直接指了 CWE-457(「使用未初始化变量」的常见漏洞名录条目), 说大量安全问题就是这么来的35。作者的建议:除非有极其过硬的理由, 把 undefined 的用途限制在缓冲区36。
注意这里又是一次「隐式 vs 显式」的交换:别的语言里「未初始化」是默认值, 悄无声息;Zig 里它必须大声说出来,而你一大声说,搜索代码库时 每一个危险点都在明处。
3.5 字符串:不是类型,是「utf-8 字节序列」的约定
拆穿第一层:Zig 没有字符串类型。 没有 string,没有 String。
Zig 对字符串的看法就是它实际上是什么:utf-8 编码的字节序列37。
(utf-8 是互联网上文字的通用编码:每个字符一到四个字节不等。)
那么「字符串」用什么类型装?——你已经学过了:[]const u8,
一个字节 slice。标准库的字符串操作函数全建在这个类型上,
任何别的编码(utf-16 之类)它也能照样处理38。
拆穿第二层:字符串字面量的类型为什么这么怪。 用内建函数 @TypeOf
问字面量 "I am a string literal" 的类型,打印出来是:
*const [21:0]u8拆开看,每一截都有理由(这是原书最得意的一段拆解)39:
| 截 | 意思 | 为什么 |
|---|---|---|
*const | 指向不可改数据的指针 | 字面量存在编译后二进制的只读区40;传指针比拷字节便宜得多 |
[21] | 21 个元素的数组 | 这个字符串恰好 21 字节;想拷成数组,直接解引用就行41 |
:0 | 结尾带一个 0 | nul terminator(C 式结尾符):C 的字符串就是「以 0 结尾的字节序列」。有了它,Zig 字面量能零开销直通 C 函数42 |
u8 | 每个元素是一个字节 | utf-8 的基本单位 |
这套设计的效果:字面量既能当数组(编译期知道长度),又能自动转成 slice (动态地用),还能直接喂给 C——一个类型,三种身份,零转换成本。 原书作者对此的评价是「深得可以又精致到荒谬」, 并给读者发了张去仙境的门票:「如果这句话让你像我同样兴奋, 欢迎来到仙境,爱丽丝」43。
3.6 汇总:原书表 2.4 的五种类型
把全章收成一张表(照原书表 2.4 的口径,略去说明列)44:
| 名字 | 写法 | 能做的操作 | 一句话 |
|---|---|---|---|
| 单元素指针 | *T、*const T | 解引用、取 [0..1] | 一个元素的地址 |
| 多元素指针 | [*]T、[*]const T | 下标、任意切片 | 一串元素,个数类型检查器不知道 |
| 数组 | [N]T | 下标、任意切片 | 值;个数编译期已知 |
| 指向数组的单元素指针 | *[N]T、*const [N]T | 下标、任意切片 | 数组的地址,个数编译期已知 |
| slice | []T、[]const T | 下标、任意切片 | 指针 + 长度;个数运行期已知 |
原书的总结:「这些类型区分说明,Zig 有着一套极其富表现力的类型系统 来写操作内存的代码」45。富表现力的意思不是「多」——总共五个—— 而是每个区分都对应一个真实的问题:谁知道长度?允不允许改? 这在签名上全看得出来。
4. 作者的判断与证据
| 判断 | 是书里给的证据,还是作者的推测 |
|---|---|
| 指针给的力量「高层抽象给不了」 | 作者经验,合理但无对照 |
| 数组「是值不是引用」是 Zig 与众不同的关键 | 语言事实,例子可跑 |
| 指针的 const 性能当函数签名的说明书 | 作者的经验法则,实用 |
| slice 是「带超能力的多元素指针」 | 准确的类比(长度 + 安全检查正是多出来的能力) |
| undefined 应限制在缓冲区 | 作者建议,附 CWE-457 佐证风险真实 |
| 字符串字面量设计「深得又精致」 | 作者鉴赏,但四个设计理由逐条可验 |
5. 边界与局限
- 越界检查只在安全模式开着。 ReleaseFast/ReleaseSmall 下 slice 越界 一样是不检查的——「安全检查」是编译档位的事,不是类型本身的事。 这呼应 02 篇边界一节说过的 Debug/Release 行为差。
- 多元素指针的「程序员自己记账」是真正的风险点: 它比 C 好不了多少,书里没有展开「什么时候值得用它」的量化标准。
undefined的陷阱比书里写的更日常:数组的一部分初始化了、 一部分 undefined,然后整体读——这种「部分初始化」错误安全模式也未必拦得住。- 字符串一节没讲 utf-8 的切片陷阱:按字节切
[]const u8, 可能把一个多字节字符切成两半。处理非 ASCII 文本时这是常见翻车点, 本节(及已放出的全部章节)未提。 - 「数组是值」的拷贝成本:大数组按值传参会真拷贝, 书给了指针方案但没讲何时拷贝反而是优化(缓存局部性)。
6. 可带走的
- 两个问题分型:一个还是多个?长度谁知道?——
*T、[*]T、[N]T、[]T全落位; &取地址、.*解引用;指针类型自带可变性:*const T不许通过它写;- 窄化收窄自动转(
*i32→*const i32),放宽不行; - 函数的指针参数收
*const就等于签名上写明「我不改你的数据」; - Zig 数组是值:赋值即全拷;要传大数组又不拷,传
*const [N]T; - slice = 指针 + 长度,
slice.ptr/slice.len随取随用; a[1..4]左闭右开,取范围必得 slice;slice 可再切;- 缓冲区 = 显式声明的数组 +
undefined,别的函数管你要[]u8; - 字符串 =
[]const u8,字面量类型*const [21:0]u8的四截各有设计理由,:0直通 C; - 越界检查依赖安全模式——release 档位要自己掂量。
7. 原文地图
| 主题 | 原书章 | 原文位置 |
|---|---|---|
| 裸机器指针与「内存地址就是数」 | 2.2 Pointing You in the Right Direction | text/13-ch02-02-2-2-pointing-you-in-the-right-direction.txt:37(搜「raw machine pointers」) · text/13-ch02-02-2-2-pointing-you-in-the-right-direction.txt:43(搜「numbers that represent a specific location」) |
| segfault 定义与「本科生刑具」 | 2.2 Pointing You in the Right Direction | text/13-ch02-02-2-2-pointing-you-in-the-right-direction.txt:53(搜「A segmentation fault」) · text/13-ch02-02-2-2-pointing-you-in-the-right-direction.txt:57(搜「torture device」) |
| 单元素指针:定义与从左往右读 | 2.2 Pointing You in the Right Direction | text/13-ch02-02-2-2-pointing-you-in-the-right-direction.txt:70(搜「single-item pointer」) · text/13-ch02-02-2-2-pointing-you-in-the-right-direction.txt:76(搜「from left to right」) |
| & 与 .* | 2.2 Pointing You in the Right Direction | text/13-ch02-02-2-2-pointing-you-in-the-right-direction.txt:105(搜「a dot followed by a star」) |
| 常指针:编译错误与「指向常量」 | 2.2 Pointing You in the Right Direction | text/13-ch02-02-2-2-pointing-you-in-the-right-direction.txt:139(搜「cannot assign to constant」) · text/13-ch02-02-2-2-pointing-you-in-the-right-direction.txt:143(搜「constant pointer」) |
| 窄化:常指针更窄、可强转 | 2.2 Pointing You in the Right Direction | text/13-ch02-02-2-2-pointing-you-in-the-right-direction.txt:150(搜「narrower type」) · text/13-ch02-02-2-2-pointing-you-in-the-right-direction.txt:156(搜「narrowness of a type refers」) |
| const 性当说明书;out parameter | 2.2 Pointing You in the Right Direction | text/13-ch02-02-2-2-pointing-you-in-the-right-direction.txt:171(搜「The const-ness of a pointer」) · text/13-ch02-02-2-2-pointing-you-in-the-right-direction.txt:175(搜「single-item pointers are often used」) |
| 数组是值;拷贝整个数组 | 2.2 Pointing You in the Right Direction | text/13-ch02-02-2-2-pointing-you-in-the-right-direction.txt:188(搜「values, not references」) · text/13-ch02-02-2-2-pointing-you-in-the-right-direction.txt:219(搜「copy the entire」) |
| 零起下标;[N]T;const 即元素 const | 2.2 Pointing You in the Right Direction | text/13-ch02-02-2-2-pointing-you-in-the-right-direction.txt:221(搜「zero-indexed」) · text/13-ch02-02-2-2-pointing-you-in-the-right-direction.txt:227(搜「Array types are spelled」) |
| [_] 让编译器数个数 | 2.2 Pointing You in the Right Direction | text/13-ch02-02-2-2-pointing-you-in-the-right-direction.txt:235(搜「compiler can figure out」) |
| 数组指针 *[N]T 与长度的天花板 | 2.2 Pointing You in the Right Direction | text/13-ch02-02-2-2-pointing-you-in-the-right-direction.txt:238(搜「looks like *[N]T」) · text/13-ch02-02-2-2-pointing-you-in-the-right-direction.txt:242(搜「of different lengths」) |
| slice 定义与 []T 写法 | 2.2 Pointing You in the Right Direction | text/13-ch02-02-2-2-pointing-you-in-the-right-direction.txt:246(搜「pointers to multiple items with a length」) · text/13-ch02-02-2-2-pointing-you-in-the-right-direction.txt:249(搜「Slice types are written」) |
| 越界检查;ptr/len;多元素指针 | 2.2 Pointing You in the Right Direction | text/13-ch02-02-2-2-pointing-you-in-the-right-direction.txt:270(搜「outside the bounds of a slice」) · text/13-ch02-02-2-2-pointing-you-in-the-right-direction.txt:279(搜「len is a usize」) · text/13-ch02-02-2-2-pointing-you-in-the-right-direction.txt:280(搜「many-item pointer」) |
| slice=超能力多元素指针;C 语义 | 2.2 Pointing You in the Right Direction | text/13-ch02-02-2-2-pointing-you-in-the-right-direction.txt:294(搜「superpowers」) · text/13-ch02-02-2-2-pointing-you-in-the-right-direction.txt:299(搜「helps encode semantics」) |
| 范围运算符 .. 与左闭右开 | 2.2 Pointing You in the Right Direction | text/13-ch02-02-2-2-pointing-you-in-the-right-direction.txt:311(搜「two dots (..)」) · text/13-ch02-02-2-2-pointing-you-in-the-right-direction.txt:327(搜「stop at the index on the right side」) |
| 取范围必得 slice | 2.2 Pointing You in the Right Direction | text/13-ch02-02-2-2-pointing-you-in-the-right-direction.txt:334(搜「always results in a slice」) |
| 缓冲区定义;undefined | 2.2 Pointing You in the Right Direction | text/13-ch02-02-2-2-pointing-you-in-the-right-direction.txt:344(搜「temporary place to store data」) · text/13-ch02-02-2-2-pointing-you-in-the-right-direction.txt:349(搜「special value undefined」) |
| undefined 的代价(CWE-457)与限制建议 | 2.2 Pointing You in the Right Direction | text/13-ch02-02-2-2-pointing-you-in-the-right-direction.txt:354(搜「created this way」) · text/13-ch02-02-2-2-pointing-you-in-the-right-direction.txt:356(搜「limiting usage of undefined」) |
| 没有字符串类型;utf-8 字节序列 | 2.2 Pointing You in the Right Direction | text/13-ch02-02-2-2-pointing-you-in-the-right-direction.txt:386(搜「dedicated string type」) · text/13-ch02-02-2-2-pointing-you-in-the-right-direction.txt:387(搜「utf-8 encoded sequences」) |
| 字面量类型 *const [21:0]u8 的逐截拆解 | 2.2 Pointing You in the Right Direction | text/13-ch02-02-2-2-pointing-you-in-the-right-direction.txt:425(搜「read-only sequence of 21」) · text/13-ch02-02-2-2-pointing-you-in-the-right-direction.txt:428(搜「copy the bytes」) · text/13-ch02-02-2-2-pointing-you-in-the-right-direction.txt:436(搜「nul terminator allows」) |
| 「欢迎来到仙境」 | 2.2 Pointing You in the Right Direction | text/13-ch02-02-2-2-pointing-you-in-the-right-direction.txt:443(搜「Wonderland」) |
| 五种类型汇总与「极富表现力的类型系统」 | 2.2 Pointing You in the Right Direction | text/13-ch02-02-2-2-pointing-you-in-the-right-direction.txt:452(搜「Table 2.4」) · text/13-ch02-02-2-2-pointing-you-in-the-right-direction.txt:498(搜「extremely expressive type system」) |
Footnotes
-
出处:「2.2 Pointing You in the Right Direction」第 33–36 段(
text/13-ch02-02-2-2-pointing-you-in-the-right-direction.txt:36,搜「unmatched by higher-level abstractions」)。原文:「Once you learn to wield pointers without grotesquely destroying your program, they provide a level of power, flexibility, and control that is simply unmatched by higher-level abstractions.」 ↩ -
出处:「2.2 Pointing You in the Right Direction」第 37 段(
text/13-ch02-02-2-2-pointing-you-in-the-right-direction.txt:37,搜「raw machine pointers」)。 ↩ -
出处:「2.2 Pointing You in the Right Direction」第 42–45 段(
text/13-ch02-02-2-2-pointing-you-in-the-right-direction.txt:43,搜「numbers that represent a specific location」)。原文:「At the end of the day, they are just memory addresses, numbers that represent a specific location in the memory of a process during the execution of your program.」 ↩ -
出处:「2.2 Pointing You in the Right Direction」第 51–56 段(SEGMENTATION FAULT 栏,
text/13-ch02-02-2-2-pointing-you-in-the-right-direction.txt:53,搜「A segmentation fault」)。原文:「A segmentation fault (or segfault) is a kind of program crash that occurs when a program attempts to access a memory address outside of the memory that the operating system has permitted the program to use.」 ↩ -
出处:「2.2 Pointing You in the Right Direction」第 56–57 段(
text/13-ch02-02-2-2-pointing-you-in-the-right-direction.txt:57,搜「torture device」)。原文:「(Based on my academic experiences, I think that one could also accurately describe segfaults as a kind of undergraduate torture device.)」 ↩ -
出处:「2.2 Pointing You in the Right Direction」第 65–77 段(2.2.1,
text/13-ch02-02-2-2-pointing-you-in-the-right-direction.txt:70,搜「single-item pointer」)。原文:「The first, and perhaps the most simple kind of pointer is called a single-item pointer. As the name implies, a value with this type contains the address of a single item in memory.」「Single-item pointer types are written using a star * followed by the type they point to, like *i32 or *bool.」 ↩ -
出处:「2.2 Pointing You in the Right Direction」第 74–76 段(
text/13-ch02-02-2-2-pointing-you-in-the-right-direction.txt:75,搜「just like the negation operator」)。原文:「In comptime terms, * is a unary operator just like the negation operator -. It takes some type T and returns the type single-item pointer to T.」 ↩ -
出处:「2.2 Pointing You in the Right Direction」第 76 段(
text/13-ch02-02-2-2-pointing-you-in-the-right-direction.txt:76,搜「from left to right」)。原文:「you can always read pointer types from left to right, just like an English sentence.」 ↩ -
出处:「2.2 Pointing You in the Right Direction」第 104–107 段(
text/13-ch02-02-2-2-pointing-you-in-the-right-direction.txt:105,搜「a dot followed by a star」)。原文:「The operator & is used to acquire the address of a value. In order to dereference a pointer (retrieve the item present at the pointer’s address), a dot followed by a star (.*) is used, mirroring the dot syntax used to access members of namespaces.」 ↩ -
出处:「2.2 Pointing You in the Right Direction」第 136–141 段(listing 2.9 的运行结果,
text/13-ch02-02-2-2-pointing-you-in-the-right-direction.txt:139,搜「cannot assign to constant」)。原文输出:error: cannot assign to constant,指向b_ptr.* = 50;一行。 ↩ -
出处:「2.2 Pointing You in the Right Direction」第 143–145 段(
text/13-ch02-02-2-2-pointing-you-in-the-right-direction.txt:143,搜「constant pointer」)。原文:「Since b_ptr is a pointer to a constant value, commonly referred to as a constant pointer, it's illegal to write a value through it. The compiler is able to catch this without any issues.」 ↩ -
出处:「2.2 Pointing You in the Right Direction」第 154–159 段(TYPE NARROWNESS 栏,
text/13-ch02-02-2-2-pointing-you-in-the-right-direction.txt:156,搜「narrowness of a type refers」)。原文:「The narrowness of a type refers to the set of properties a type encodes. A type that is narrower than another type has more constraints, even if it may share the same underlying value.」 ↩ -
出处:「2.2 Pointing You in the Right Direction」第 150–153 段(
text/13-ch02-02-2-2-pointing-you-in-the-right-direction.txt:150,搜「narrower type」)。原文:「Since constant pointers are a narrower type than mutable pointers, Zig is totally okay with allowing you to coerce a mutable pointer to a constant pointer.」 ↩ -
出处:「2.2 Pointing You in the Right Direction」第 169–173 段(
text/13-ch02-02-2-2-pointing-you-in-the-right-direction.txt:171,搜「The const-ness of a pointer」)。原文:「If a function doesn't plan to mutate the underlying data, there is no need to demand a mutable pointer type. The const-ness of a pointer is often able to provide us with a lot of information about how some code we're reusing works!」 ↩ -
出处:「2.2 Pointing You in the Right Direction」第 174–178 段(
text/13-ch02-02-2-2-pointing-you-in-the-right-direction.txt:175,搜「single-item pointers are often used」)。原文:「In the wild, single-item pointers are often used to write functions that manipulate data, to store references in data structures, and to interact with C APIs that write data through a pointer, referred to as an out parameter.」 ↩ -
出处:「2.2 Pointing You in the Right Direction」第 182–187 段(2.2.2,
text/13-ch02-02-2-2-pointing-you-in-the-right-direction.txt:184,搜「confounding」)。原文:「my first experiences working with arrays in Zig could be described using adjectives like confounding and floundering.」 ↩ -
出处:「2.2 Pointing You in the Right Direction」第 187–189 段(
text/13-ch02-02-2-2-pointing-you-in-the-right-direction.txt:188,搜「values, not references」)。原文:「The key difference between Zig's arrays and arrays in most mainstream C-like languages is that Zig's arrays are values, not references.」 ↩ -
出处:「2.2 Pointing You in the Right Direction」第 219–223 段(
text/13-ch02-02-2-2-pointing-you-in-the-right-direction.txt:219,搜「copy the entire」)。原文:「Since arrays are values, when you copy a variable of an array type, you copy the entire array.」 ↩ -
出处:「2.2 Pointing You in the Right Direction」第 221–223 段(
text/13-ch02-02-2-2-pointing-you-in-the-right-direction.txt:221,搜「zero-indexed」)。原文:「Zig arrays are zero-indexed. This means that index 0 refers to the first element, 1 to the second element, and 2 to the third.」 ↩ -
出处:「2.2 Pointing You in the Right Direction」第 224–226 段(
text/13-ch02-02-2-2-pointing-you-in-the-right-direction.txt:224,搜「const-ness of the」)。原文:「since Zig arrays are values, the const-ness of the array is also the const-ness of its elements.」 ↩ -
出处:「2.2 Pointing You in the Right Direction」第 227 段(
text/13-ch02-02-2-2-pointing-you-in-the-right-direction.txt:227,搜「Array types are spelled」)。原文:「Array types are spelled [N]T, where N is the number of elements and T is the type of the elements.」 ↩ -
出处:「2.2 Pointing You in the Right Direction」第 232–235 段(listing 2.12,
text/13-ch02-02-2-2-pointing-you-in-the-right-direction.txt:235,搜「compiler can figure out」)。原文:「The compiler can figure out that this is still an [3]i32.」 ↩ -
出处:「2.2 Pointing You in the Right Direction」第 237–240 段(
text/13-ch02-02-2-2-pointing-you-in-the-right-direction.txt:238,搜「looks like *[N]T」)。原文:「One solution is to use a single-item pointer to an array, which looks like *[N]T in code.」「If you want to avoid a copy, you could make the pointer constant, too: *const [N]T.」 ↩ -
出处:「2.2 Pointing You in the Right Direction」第 245–248 段(2.2.3,
text/13-ch02-02-2-2-pointing-you-in-the-right-direction.txt:246,搜「pointers to multiple items with a length」)。原文:「Slices are pointers to multiple items with a length attached. They act a lot like an array, in that you can index into them to store or retrieve data. However, they are still just pointers — they always reference data stored somewhere else.」 ↩ -
出处:「2.2 Pointing You in the Right Direction」第 249–251 段(
text/13-ch02-02-2-2-pointing-you-in-the-right-direction.txt:249,搜「Slice types are written」)。原文:「Slice types are written []T, where T is the element type.」「Like other pointer types, slices can be const - written []const T.」 ↩ -
出处:「2.2 Pointing You in the Right Direction」第 274–277 段(
text/13-ch02-02-2-2-pointing-you-in-the-right-direction.txt:276,搜「the slice will」)。原文:「A single-item pointer to an array is a pointer to multiple elements, with a length that is known at comptime, so the slice will point to the beginning of the array and take the length of the entire array.」 ↩ -
出处:「2.2 Pointing You in the Right Direction」第 278–282 段(
text/13-ch02-02-2-2-pointing-you-in-the-right-direction.txt:279,搜「len is a usize」;:280,搜「many-item pointer」)。原文:「the ptr (pointer) and len (length) fields of the slice can be accessed via the dot syntax. len is a usize, just like indices. ptr is actually a type we haven't seen before, called a many-item pointer.」 ↩ -
出处:「2.2 Pointing You in the Right Direction」第 270–272 段(TIP,
text/13-ch02-02-2-2-pointing-you-in-the-right-direction.txt:270,搜「outside the bounds of a slice」)。原文:「When compiling in safe mode, if you try to access an index outside the bounds of a slice, you will see an error and a stack trace! This allows you to catch out-of-bounds errors before they cause real problems.」 ↩ -
出处:「2.2 Pointing You in the Right Direction」第 284–291 段(MANY-ITEM POINTERS 栏,
text/13-ch02-02-2-2-pointing-you-in-the-right-direction.txt:284,搜「MANY-ITEM POINTERS」)。原文:「Many-item pointer types are written []T or []const T」「These pointers represent the address of some number of elements - the compiler doesn't know how many, but the programmer will need to keep track in order to avoid accessing invalid memory.」 ↩ -
出处:「2.2 Pointing You in the Right Direction」第 294–297 段(
text/13-ch02-02-2-2-pointing-you-in-the-right-direction.txt:294,搜「superpowers」)。原文:「Slices are a lot like many-item pointers with superpowers. It's much nicer to use a pointer that has safety checks, and having the len field on hand is a lovely convenience.」「if you wish to avoid storing the len field - for example, for optimized data structures - it can make sense to use a many-item pointer.」 ↩ -
出处:「2.2 Pointing You in the Right Direction」第 298–301 段(
text/13-ch02-02-2-2-pointing-you-in-the-right-direction.txt:299,搜「helps encode semantics」)。原文:「C code often uses pointers to represent many elements. When working with C, Zig's many-item pointer type helps encode semantics that can't be represented directly in C.」 ↩ -
出处:「2.2 Pointing You in the Right Direction」第 310–313 段(
text/13-ch02-02-2-2-pointing-you-in-the-right-direction.txt:311,搜「two dots (..)」)与第 327–328 段(text/13-ch02-02-2-2-pointing-you-in-the-right-direction.txt:327,搜「stop at the index on the right side」)。原文:「the range operator, spelled out as two dots (..)」「Ranges include the index on the left side, and stop at the index on the right side.」 ↩ -
出处:「2.2 Pointing You in the Right Direction」第 334–336 段(
text/13-ch02-02-2-2-pointing-you-in-the-right-direction.txt:334,搜「always results in a slice」)。原文:「Retrieving a range from an array always results in a slice. In fact, this operation can be referred to as slicing or taking a slice. You can take a slice of a slice, just like you can take a slice of an array!」 ↩ -
出处:「2.2 Pointing You in the Right Direction」第 342–346 段(2.2.4,
text/13-ch02-02-2-2-pointing-you-in-the-right-direction.txt:344,搜「temporary place to store data」)。原文:「A buffer is simply a temporary place to store data. Many Zig functions will expect you, the programmer, to pass a buffer in by parameter in order for the function to operate. This typically takes the form of a []u8, a slice of mutable bytes.」 ↩ -
出处:「2.2 Pointing You in the Right Direction」第 352–355 段(TIP,
text/13-ch02-02-2-2-pointing-you-in-the-right-direction.txt:354,搜「created this way」)。原文:「if you ever read a value that was not uninitialized, the results are unpredictable and can have terrible consequences. A lot of security issues have been created this way (check out https://cwe.mitre.org/data/definitions/457.html).」(链接照录原书,查阅于 2026-10-19) ↩ -
出处:「2.2 Pointing You in the Right Direction」第 356–357 段(
text/13-ch02-02-2-2-pointing-you-in-the-right-direction.txt:356,搜「limiting usage of undefined」)。原文:「I would recommend limiting usage of undefined to buffers unless you have an incredibly good reason to use it in a different case.」 ↩ -
出处:「2.2 Pointing You in the Right Direction」第 384–390 段(2.2.5,
text/13-ch02-02-2-2-pointing-you-in-the-right-direction.txt:386,搜「dedicated string type」)。原文:「Zig actually does not have any kind of dedicated string type. Instead, we typically just think about strings as what they usually are on modern systems — utf-8 encoded sequences of bytes.」 ↩ -
出处:「2.2 Pointing You in the Right Direction」第 388–392 段(
text/13-ch02-02-2-2-pointing-you-in-the-right-direction.txt:388,搜「utf-16」)。原文:「you may be appeased to learn that Zig's standard library is happy to perform any of the string operations it provides with any underlying integer type or encoding.」 ↩ -
出处:「2.2 Pointing You in the Right Direction」第 414–438 段(listing 2.16 的输出与逐条拆解,
text/13-ch02-02-2-2-pointing-you-in-the-right-direction.txt:417,搜「*const [21:0]u8」)。原文输出即*const [21:0]u8;拆解为紧随其后的四个要点。 ↩ -
出处:「2.2 Pointing You in the Right Direction」第 424–425 段(
text/13-ch02-02-2-2-pointing-you-in-the-right-direction.txt:425,搜「read-only sequence of 21」)。原文:「The string literal is stored in the compiled binary of the program as a read-only sequence of 21 utf-8 encoded bytes.」 ↩ -
出处:「2.2 Pointing You in the Right Direction」第 428–429 段(
text/13-ch02-02-2-2-pointing-you-in-the-right-direction.txt:428,搜「copy the bytes」)。原文:「If you wanted to copy the bytes as an array, you could just dereference the string!」 ↩ -
出处:「2.2 Pointing You in the Right Direction」第 433–438 段(
text/13-ch02-02-2-2-pointing-you-in-the-right-direction.txt:436,搜「nul terminator allows」)。原文:「since C's model of strings is simply a sequence of bytes with a nul terminator. Having a nul terminator allows Zig's string literals to be passed directly to C functions with absolutely zero layers of abstraction or overhead in between.」 ↩ -
出处:「2.2 Pointing You in the Right Direction」第 440–444 段(
text/13-ch02-02-2-2-pointing-you-in-the-right-direction.txt:443,搜「Wonderland」)。原文:「It demonstrates the kind of deeply grounded—yet ridiculously polished design choices—that Zig will continue to surprise you with. If this statement excites you as much as it does me, then welcome to Wonderland, Alice.」 ↩ -
出处:「2.2 Pointing You in the Right Direction」第 447–498 段(表 2.4,
text/13-ch02-02-2-2-pointing-you-in-the-right-direction.txt:452,搜「Table 2.4」)。五行类型及其「Operations / Explanation」列均照表。 ↩ -
出处:「2.2 Pointing You in the Right Direction」第 498–501 段(
text/13-ch02-02-2-2-pointing-you-in-the-right-direction.txt:498,搜「extremely expressive type system」)。原文:「As all of these type distinctions demonstrate, Zig has an extremely expressive type system for writing code that deals with memory.」 ↩