数组、向量与字符串 — 基本类型(下)¶
这一章讲两件事: 数组、向量、切片这三个序列(一个接一个排成一列的值)类型谁干什么、怎么互相转; String 和 &str 为什么是两个类型、
len()为什么经常「数错」。 上一章讲原子,这一章讲由原子组成的第一批分子——后面所有数据结构都长在这层上。
1. 顶层全景:三种序列,一条借用链¶
[T; N] 数组:定长,长度是类型的一部分,在栈上
│ 太长/要运行时定长?
▼
Vec<T> 向量:堆上,可增长 = 指针 + 容量 + 长度 三个机器字
│ 只想借一段,不想接管?
▼
&[T] / &mut [T] 切片引用:胖指针 = 数据地址 + 元素个数
图说:从左到右,拥有的程度递减、灵活性递增。函数参数几乎总该选最右边那个。
本章的主线例子是曼德博程序里那个像素缓冲:1200 万字节怎么从 vec! 创建、
怎么被 render(&mut [u8]) 借用、最后怎么被 write_image(&[u8]) 只读借用——三种序列类型各走一步。
2. 数组:长度写进类型里¶
[T; N] 是定长数组:长度是编译期常量,是类型的一部分,不能伸缩1。两种写法:
let lazy_caterer: [u32; 6] = [1, 2, 4, 7, 11, 16]; // 逐个列
let mut sieve = [true; 10000]; // [值; 个数]:一万个 true
[0u8; 1024] 是经典用法:一个 1 KB 的零填充缓冲区。有个细节很 Rust:
没有「未初始化数组」的写法——一般说来,Rust 保证代码永远碰不到未初始化的值2。
下标越界会怎样?Rust 每次访问都检查,越界就 panic——不是 undefined behavior,不是静默读错内存3。
下标类型还必须是 usize(别的整数类型不行)4。
有个语法边界:长度是变量时不能写 [true; n]——需要运行时定长就用向量5。
3. 向量:三个机器字加一个堆块¶
Vec<T> 是可增长序列,元素住堆里。创建姿势:
vec![v; n] 建 n 个 v 的副本;collect 能造好几种集合,所以得告诉它你要 Vec<i32>6。
向量的内部结构是三个机器字:指向堆缓冲的指针、容量(这块缓冲最多装几个)、长度(现在装几个)。
容量满了再 push,就分配更大的缓冲、拷贝过去、更新指针和容量、释放旧的7。
知道大概需要多少就先 Vec::with_capacity(n),免去中途反复重分配——collect 内部就是这么优化的8。
capacity() 能看容量:往容量 2 的向量 push 第 3 个元素后,容量通常变 4(不保证恰好,只保证够用)9。
改内容的操作都有:中间插删(insert/remove,后面的元素要整体搬家,长向量上慢)、
pop 弹尾元素——注意 pop 返回 Option<T>:空向量弹不出东西,是 None 而不是报错10。
数组的活用:一万个 bool 当筛子¶
原书用一个经典小算法展示 [V; N] 语法——埃拉托斯特尼筛法找素数:
let mut sieve = [true; 10000];
for i in 2..100 {
if sieve[i] {
let mut j = i * i; // 从 i² 开始划掉倍数
while j < 10000 {
sieve[j] = false;
j += i;
}
}
}
assert!(sieve[211]); // 211 是素数
assert!(!sieve[9876]); // 9876 不是
[true; 10000] 一次造出一万个 true,不用写一万遍——这就是「定长缓冲」语法的典型用途30。
向量的实战小例子:按名字长度分类¶
原书还有一个调皮的小程序,顺带演示「收集迭代器」和「遍历向量」:
let languages: Vec<String> = std::env::args().skip(1).collect();
for l in languages {
println!("{l}: {}", if l.len() % 2 == 0 { "functional" } else { "imperative" });
}
命令行传入 Lisp、Scheme、C、C++、Fortran,输出:
原书自己抖的包袱:「函数式语言的一个令人满意的定义,终于得出来了。」31
(按名字长度奇偶分类只是个玩笑,但这个例子里 collect 把参数迭代器收成 Vec<String>、
for 逐个消费——两个惯用法都是真的。)
4. 切片:序列的「视图」¶
切片 [T](不带长度)是数组或向量里的一段。它本身不能存进变量、不能直接传参——
总是借引用出现:&[T] 或 &mut [T]11。
为什么切片引用要单独是个类型?因为它和普通引用不一样,是胖指针(fat pointer):
普通引用 &T 是一个机器字(地址);切片引用是两个——数据地址 + 元素个数12。
切片是这条借用链的枢纽,三个证据:
- 数组和向量「自动降级」成切片:
print(&a)、print(&v)、print(&v[0..2])都喂给同一个fn print(n: &[f64])13。 - 数组/向量好用的方法(
sort、reverse、len)其实都定义在切片上—— 调用时 Rust 隐式借一个覆盖整体的切片出来14。 - 函数参数该要切片就要切片:参数写
&Vec<f64>就只收完整向量,&v[0..2]都传不进去; 写&[f64]则数组、向量、片段通吃。原书把这当一条通用建议:能收切片引用就别收向量/数组引用15。
回到主线例子:曼德博的 render(pixels: &mut [u8], …) 收的是可变切片——
它不关心这 1200 万字节来自整个向量还是哪条带,往里写就是了;
write_image(pixels: &[u8], …) 收共享切片,保证写文件的人只读16。
并发版里 chunks_mut 把整缓冲切成互不重叠的可变切片,正是这一层的直接运用。
切片的区间语法与边界检查¶
取一段的写法是一个区间:&v[0..2](头两个)、&a[2..](从 2 到尾)、&sv[1..3](切片再切片)。
规则和下标访问一样:越界就 panic——想借一段超出数据末尾的切片,编译器放过你(下标是运行时的),
运行时在边界检查上拦住32。
为什么函数参数推荐切片?书里给的完整论证是:若 print 收 &Vec<f64>,就只能收完整向量,
&v[0..2] 这种片段传不进去;收 &[f64] 则来者不拒。接口按切片设计,实现者自由,调用者也自由——
sort、reverse 定义在切片上而非 Vec<T> 上,就是这个原则的既有实践33。
5. String 与 &str:抄 Vec 与 &[T] 的作业¶
字符串在 Rust 里是两个类型,关系照抄向量那一对:
| Vec<T> | String | |
|---|---|---|
| 拥有缓冲、可增长、自动释放 | 是 | 是 |
::new() / ::with_capacity() |
有 | 有 |
.reserve() / .capacity() |
有 | 有 |
.push() / .pop() |
有 | 有 |
区间切片 &v[a..b] |
得 &[T] |
得 &str |
&Vec<T> 自动转 |
&[T] |
&String → &str |
| 方法继承自 | &[T] |
&str |
原书原话:「&str 很像 &[T];String 类比 Vec<T>。」17
内存布局:String 是一个堆上缓冲、持有它、内容保证是合法 UTF-8(实现上就是
「保证内容形式良好的 Vec<u8>」);&str 是胖指针——借来的 UTF-8 文本,地址加长度18。
字符串字面量(如 "ಠ_ಠ")是 &str,指向程序机器码旁边那块只读内存,程序启动就在、退出才走19。
char 是另一回事:一个 char 占 4 字节,它存一个独立字符在 Unicode(全世界字符的统一编号体系)里的编号,宽度和 u32 一样。
字符串本体却按 UTF-8 变长编码存:ASCII 字符 1 字节,其他字符 2–4 字节—— 所以 char 和字符串里的字节不是一回事20。
由此得出一个会咬人的事实:.len() 数的是字节,不是字符。
「ಠ」每个 3 字节、下划线 1 字节,7 = 3+1+321。
再由此得出一个类型学结论:String/&str/char 都是带不变式(invariant)的类型——
实现层强制遵守的值规则(UTF-8 合法、Unicode 标量(一个独立字符的编号)合法),除了滥用 unsafe 代码外无法破坏,
程序可以放心依赖22。这是「类型即承诺」的第一个实例,后面所有权的论证全靠这类承诺。
从图 2-3 重放:String、&str、str 的内存¶
书上有张经典插图(图 2-3),把三个概念钉在同一张图上,用语言重放:
let noodles = "noodles".to_string(); // String
let oodles = &noodles[1..]; // &str,借后 6 字节
let disapproodles = "ಠ_ಠ"; // &str,字面量
noodles(String):栈上三字段(指针、容量 8、长度 7),指针指着堆上 8 字节的缓冲, 其中 7 个在用。String 是主人;oodles(&str):胖指针——地址 + 长度 6。它指向 noodles 缓冲的内部,不拥有;disapproodles(&str):同样胖指针,但指向程序机器码旁边的只读内存,程序一辈子都在47。
三个名字、三种身份:一个主人、两种借用。所有字符串问题的答案,几乎都能从这张图推出来。
6. 使用与拼写¶
创建和拼接:
let error_message = "too many pets".to_string(); // &str → String(拷贝)
let place = format!("Hello, {place}!"); // 拼成新 String
let bits = vec!["veni", "vidi", "vici"];
bits.join(", "); // "veni, vidi, vici"
format! 和 println! 同款模板,只是返回字符串不打印;{} 用 Display 格式(给人看),
{:?} 用 Debug 格式(给调试看,带引号转义)——元组、切片、Vec、Option 都得用 {:?} 才打印得出来23。
比较与常用方法:== 按内容比(不看地址);contains、replace、trim、split、
starts_with……文档在「Primitive Type str」词条24。
&str 不可改:没有 push,不能按下标赋值——想生成新文本,用 String25。
选型建议(第 4 章详谈):参数优先 &str,和「参数优先切片」同一条逻辑26。
转义序列、原始字符串与 C 串字面量¶
字符串里的特殊字符用反斜杠转义(text/12 表 2-6)34:
| 要写的字符 | 写法 |
|---|---|
| 单引号、反斜杠 | \'、\\ |
| 换行、回车、制表 | \n、\r、\t |
| 任意 ASCII | \x 加两个十六进制位 |
| 任意字符 | \u{…} 加至多六个十六进制位 |
字符串可以跨行,换行和缩进空格都算内容;行尾加一个反斜杠,就能「吃掉」换行和下一行的前导空格, 把长字符串折行排版35。
两个场景让「每个反斜杠写两遍」变成灾难:正则表达式、Windows 路径。
对策是原始字符串:以 r 开头,内容原样收录,不识别任何转义——r"C:\Program Files\Gorillas"。
想内含双引号?给两头加 # 号:r#"…"#,多少个 # 都行,只要内容里没出现同数量的 "#36。
b"…" 是字节串(类型 &[u8; N],内容不要求是合法 UTF-8——b"\x7fELF" 是几乎每个 Linux
可执行文件开头的魔数);c"…" 是 C 串(零结尾,类型 &CStr,为对接 C API 准备)37。
拼接与格式化¶
造字符串的三件套:to_string() 拷贝一份、format! 按模板拼、concat/join 连列表。
格式串里 {} 是 Display 格式(给人看),{:?} 是 Debug 格式(给调试看:字符串带引号、
特殊字符转义)。不是所有类型都支持 Display,但几乎所有类型都支持 Debug——
想打印元组、切片、Vec、Option,只有 {:?} 这一条路38。
字符串比较按内容不按地址:"ONE".to_lowercase() == "one" 成立。
常用方法一带而过:contains、replace、trim、split、字符的 is_alphabetic、
to_digit……文档都在「Primitive Type str / char」词条下39。
7. 其他「像字符串的类型」和字节串¶
Rust 保证字符串是合法 UTF-8,但操作系统不保证(文件名、环境变量(操作系统传给程序的一批键值对)可以是任意字节)。 对策是一排特化类型,按场景换用27:
| 场景 | 用 |
|---|---|
| 普通文本 | String / &str |
| 文件名 | PathBuf / &Path |
| 环境变量、命令行参数(可能是非 UTF-8) | OsString / OsStr |
| 根本不是文本的二进制 | Vec<u8> / &[u8] |
| 和 C 库互操作(零结尾串) | CString / CStr |
两种特殊字面量:b"…" 是字节串(类型 &[u8; N],不需要合法 UTF-8——
b"\x7fELF" 就是几乎每个 Linux 可执行文件开头的那 4 个魔数字节);
c"…" 是 C 串(零结尾,类型 &CStr)28。
收尾一个轻量特性:type 关键字给已有类型起别名(对标 C++ 的 typedef):
type Bytes = Vec<u8>;——新名字,不是新类型29。
表 2-1 的用法:一张总览当字典¶
原书第 2 章开头有一张「全书类型总览表」(表 2-1),性质是字典不是课文: 每种类型一行,给名字、一句话描述、一个值的样子。把它当回查表用,遇到没见过的类型先在这里对号入座40:
| 类型 | 一句话 | 值的样子 |
|---|---|---|
| i8…i128 / u8…u128 | 定宽整数 | 42、-5i8、0x400u16 |
| isize / usize | 机器字长整数 | 137、下标、长度 |
| f32 / f64 | IEEE 浮点 | 1.0、6.0221e23 |
| bool | 布尔 | true、false |
| (char, u8, i32) | 元组 | ('%', 0x7f, -1) |
| () | 单元 | () |
| struct S | 具名字段结构体 | S { x: 120.0, y: 209.0 } |
| struct T(i32, char) | 元组式结构体 | T(120, 'X') |
| struct E; | 单元式结构体 | E |
| enum Attend | 枚举 | Attend::Late(5) |
| Box<T> | 堆上独占指针 | Box::new(v) |
| &T / &mut T | 共享 / 可变引用 | &s.y、&mut v |
| String | 堆上 UTF-8 文本 | "…".to_string() |
| &str | 借来的 UTF-8 文本 | "…"、&s[0..12] |
| char | Unicode 字符 | '字'、'\n'、'\u{CA0}' |
| [f64; 4] | 定长数组 | [1.0, 0.0, 0.0, 1.0] |
| Vec<f64> | 可增长向量 | vec![0.367, 2.718] |
| &[u8] / &mut [u8] | 切片引用 | &v[10..20] |
| Option<&str> | 可选值 | Some("Dr.")、None |
| Result<u64, Error> | 可失败的结果 | Ok(4096)、Err(…) |
| &dyn Error 等 | trait 对象引用 | &err as &dyn Error |
| fn(&str) -> bool | 函数指针 | str::is_empty |
| 闭包 | (无书面类型) | \|a, b\| { a*a + b*b } |
表里的大多数本章已讲;struct/enum/trait 对象/闭包各有专章——总览表的价值在于: 今天读到这里,回查一下「这个类型站在哪一层」。
容量与长度:一个看得见的实验¶
len 是现在装几个,capacity 是最多不用搬家能装几个。书上的实验41:
let mut v = Vec::with_capacity(2);
assert_eq!(v.len(), 0);
assert_eq!(v.capacity(), 2);
v.push(1); v.push(2); // 正好装满,不搬家
assert_eq!(v.len(), 2);
assert_eq!(v.capacity(), 2);
v.push(3); // 装不下了:换大缓冲
assert_eq!(v.len(), 3);
// 通常打印 "capacity is now 4":
println!("capacity is now {}", v.capacity());
容量变 4 不保证(只保证 ≥3)——增长策略是实现细节。这个「不保证」本身也是教材: 依赖未承诺的行为,是 C 的老毛病;读 len/capacity 的值做决策,而不是猜实现42。
中间插入与删除:快的假象与真的代价¶
insert 和 remove 都收得下标,但书上的提醒很直白:它们会把受影响位置之后的
所有元素整体搬一次家——在长的向量中间插一个,后面一百万个元素各挪一格。
短向量无感,长向量是性能事故。常用的尾部操作(push/pop)才是不搬家的那档43。
UTF-8 一句话版(补充,不在书里的展开)¶
书里只给了结论:ASCII 字符 1 字节,其他字符 2–4 字节。展开一句方便建立直觉: UTF-8 是一种「编号小的字符省空间」的编码——常用的英文字母、数字一个字节, 汉字、日文通常三个,「emoji」四个。一份以英文为主的日志,UTF-8 存储几乎不花额外空间, 这就是它取代定宽编码统治了万维网的原因(补充,不在书里,来自通用知识)。 Rust 选 UTF-8 作字符串本体,等于免费继承了这个生态44。
由此而来的两个使用纪律:其一,len() 数字节,判长度想数字符就用 .chars().count();
其二,按下标或区间切字符串可能切在字符中间(那 7 个字节的 "ಠ_ಠ" 切成前 4 字节就不成字符),
Rust 对字符串切片按字符边界检查,切歪了 panic——原书把细节留给了字符串专章,
这里只需记住「字符串的下标是字节,不是字符」45。
&str 还是 String:参数选型的一句话¶
函数参数优先 &str——它和「参数优先切片而非向量」是同一个道理:
&str 能指向字面量、能指向 String、能指向任何字符串的一段,String 只指向自己拥有的那份。
调用方不用为你多拷贝一次,接口也宽。什么时候真的需要 String?
函数要存下这段文本、或要把它改长改短的时候——那就连所有权一起收进来46。
8. 作者的判断与证据¶
- 「函数该收切片引用」是原书明确推荐的工程惯例,理由是泛用性——证据是
sort/reverse定义在切片上这个既成事实15。 - 「len 按字节」是 UTF-8 决定的客观事实,不是设计口味;原书用
ಠ_ಠ的例子把它钉死21。 - 「类型带不变式」是 Rust 安全论证的地基性主张:unsafe 之外无法破坏——这是语言承诺22。
9. 边界与局限¶
- UTF-8 的编码细节(代理对、组合字符)原书没展开;按字节数切片可能在字符中间切断, 这个坑原书留在字符串专章([Link to Come]);
- PathBuf/OsString/CString 只给了选型表,用法没有示例;
- Vec 的高级方法、
collect的机制都指向未放出的章节。
10. 可带走的¶
主线例子一行版: vec![0; 1200 万] 建缓冲 → &mut [u8] 借给 render 写入 → chunks_mut 切成条带 →
&[u8] 只读借给 write_image。
- 数组定长、长度是类型的一部分;运行时定长用 Vec;
- 没有未初始化数组——Rust 保证你碰不到未初始化的值;
- 下标越界 panic(不是 undefined behavior),下标必须是 usize;
- Vec = 指针 + 容量 + 长度三个机器字;容量满则换新缓冲拷贝;
- 切片引用是胖指针:地址 + 长度;数组、向量自动降级成切片;
- 函数参数能收
&[T]就别收&Vec<T>——sort/reverse 定义在切片上就是这个道理; - String 类比 Vec<u8>(保证 UTF-8),&str 类比 &u8;
len()数字节不数字符:"ಠ_ಠ".len()是 7,.chars().count()是 3;- char 恒 4 字节(Unicode 标量),字符串本体按 UTF-8 变长存储;
- 非 UTF-8 场景有专门的类型:文件名 PathBuf、命令行 OsString、二进制 Vec<u8>、C 串 CString。
11. 原文地图¶
| 主题 | 原书章 | 原文位置 |
|---|---|---|
| 三种序列类型总览 | Chapter 2. Fundamental Types | text/12-ch02-chapter-2-fundamental-types.txt:525(搜「fixed-size array」) |
| 无未初始化数组 | Chapter 2. Fundamental Types | text/12-ch02-chapter-2-fundamental-types.txt:559(搜「uninitialized array」) |
| 下标检查与 usize | Chapter 2. Fundamental Types | text/12-ch02-chapter-2-fundamental-types.txt:531(搜「panics」) |
| Vec 三机器字与扩容 | Chapter 2. Fundamental Types | text/12-ch02-chapter-2-fundamental-types.txt:620(搜「three values」) |
| with_capacity 与 collect | Chapter 2. Fundamental Types | text/12-ch02-chapter-2-fundamental-types.txt:622(搜「with_capacity」) |
| insert/remove/pop | Chapter 2. Fundamental Types | text/12-ch02-chapter-2-fundamental-types.txt:644(搜「insert」) · text/12-ch02-chapter-2-fundamental-types.txt:656(搜「pop」) |
| 切片与胖指针 | Chapter 2. Fundamental Types | text/12-ch02-chapter-2-fundamental-types.txt:699(搜「fat pointer」) |
| 参数该收切片 | Chapter 2. Fundamental Types | text/12-ch02-chapter-2-fundamental-types.txt:734(搜「slice references rather than」) |
| String/&str 类比 Vec/&[T] | Chapter 2. Fundamental Types | text/12-ch02-chapter-2-fundamental-types.txt:850(搜「analogous to」) |
| 内存布局与不变式 | Chapter 2. Fundamental Types | text/12-ch02-chapter-2-fundamental-types.txt:825(搜「resizable buffer」) · text/12-ch02-chapter-2-fundamental-types.txt:829(搜「invariants」) |
| len 数字节 | Chapter 2. Fundamental Types | text/12-ch02-chapter-2-fundamental-types.txt:835(搜「bytes, not characters」) |
| 字符串字面量住只读内存 | Chapter 2. Fundamental Types | text/12-ch02-chapter-2-fundamental-types.txt:833(搜「read-only memory」) |
| 其他字符串类型选型 | Chapter 2. Fundamental Types | text/12-ch02-chapter-2-fundamental-types.txt:957(搜「PathBuf」) |
| 字节串与 C 串字面量 | Chapter 2. Fundamental Types | text/12-ch02-chapter-2-fundamental-types.txt:973(搜「byte string」) · text/12-ch02-chapter-2-fundamental-types.txt:977(搜「null-terminated」) |
| 素数筛与数组语法 | Chapter 2. Fundamental Types | text/12-ch02-chapter-2-fundamental-types.txt:545(搜「sieve」) |
| proglangs 分类例子 | Chapter 2. Fundamental Types | text/12-ch02-chapter-2-fundamental-types.txt:671(搜「functional」) |
| 转义序列与原始字符串 | Chapter 2. Fundamental Types | text/12-ch02-chapter-2-fundamental-types.txt:767(搜「escape sequences」) · text/12-ch02-chapter-2-fundamental-types.txt:797(搜「raw string」) |
| 拼接与格式化 | Chapter 2. Fundamental Types | text/12-ch02-chapter-2-fundamental-types.txt:902(搜「format specifier」) |
| 表 2-1 类型总览 | Chapter 2. Fundamental Types | text/12-ch02-chapter-2-fundamental-types.txt:41(搜「Table 2-1」) |
| 容量与长度实验 | Chapter 2. Fundamental Types | text/12-ch02-chapter-2-fundamental-types.txt:639(搜「capacity is now」) |
| 插删的搬家成本 | Chapter 2. Fundamental Types | text/12-ch02-chapter-2-fundamental-types.txt:644(搜「shift all the elements」) |
| &str 还是 String | Chapter 2. Fundamental Types | text/12-ch02-chapter-2-fundamental-types.txt:923(搜「preferable to String」) |
| 图 2-3 内存布局重放 | Chapter 2. Fundamental Types | text/12-ch02-chapter-2-fundamental-types.txt:821(搜「noodles」) |
| type 别名 | Chapter 2. Fundamental Types | text/12-ch02-chapter-2-fundamental-types.txt:983(搜「typedef」) |
-
出处:「Chapter 2. Fundamental Types」第 525–527 段(
text/12-ch02-chapter-2-fundamental-types.txt:525-527,搜「fixed-size array」)。 ↩ -
出处:「Chapter 2. Fundamental Types」第 559 段(
text/12-ch02-chapter-2-fundamental-types.txt:559,搜「uninitialized array」)。 ↩ -
出处:「Chapter 2. Fundamental Types」第 531 段(
text/12-ch02-chapter-2-fundamental-types.txt:531,搜「panics」)。 ↩ -
出处:「Chapter 2. Fundamental Types」第 531 段(
text/12-ch02-chapter-2-fundamental-types.txt:531,搜「usize value」)。 ↩ -
出处:「Chapter 2. Fundamental Types」第 561 段(
text/12-ch02-chapter-2-fundamental-types.txt:561,搜「use a vector instead」)。 ↩ -
出处:「Chapter 2. Fundamental Types」第 575–606 段(
text/12-ch02-chapter-2-fundamental-types.txt:575-606,搜「vec! macro」)。 ↩ -
出处:「Chapter 2. Fundamental Types」第 620 段(
text/12-ch02-chapter-2-fundamental-types.txt:620,搜「three values」)。 ↩ -
出处:「Chapter 2. Fundamental Types」第 622–624 段(
text/12-ch02-chapter-2-fundamental-types.txt:622-624,搜「pre-allocate」)。 ↩ -
出处:「Chapter 2. Fundamental Types」第 626–642 段(
text/12-ch02-chapter-2-fundamental-types.txt:626-642,搜「capacity is now」)。 ↩ -
出处:「Chapter 2. Fundamental Types」第 644–661 段(
text/12-ch02-chapter-2-fundamental-types.txt:644-661,搜「Option<T>」)。 ↩ -
出处:「Chapter 2. Fundamental Types」第 697–699 段(
text/12-ch02-chapter-2-fundamental-types.txt:697-699,搜「always passed by reference」)。 ↩ -
出处:「Chapter 2. Fundamental Types」第 699 段(
text/12-ch02-chapter-2-fundamental-types.txt:699,搜「fat pointer」)。 ↩ -
出处:「Chapter 2. Fundamental Types」第 715–730 段(
text/12-ch02-chapter-2-fundamental-types.txt:715-730,搜「range」)。 ↩ -
出处:「Chapter 2. Fundamental Types」第 563–569 段(
text/12-ch02-chapter-2-fundamental-types.txt:563-569,搜「implicitly converts」)。 ↩ -
出处:「Chapter 2. Fundamental Types」第 734 段(
text/12-ch02-chapter-2-fundamental-types.txt:734,搜「slice references rather than」)。 ↩↩ -
render 的切片参数见「Plotting the Set」第 32 段(
text/08-fm-plotting-the-set.txt:32,搜「mutable reference」);write_image 见「Writing Image Files」第 11–15 段(text/09-fm-writing-image-files.txt:11-15,搜「pixels: &[u8]」)。 ↩ -
出处:「Chapter 2. Fundamental Types」第 850 段(
text/12-ch02-chapter-2-fundamental-types.txt:850,搜「analogous to」)。 ↩ -
出处:「Chapter 2. Fundamental Types」第 825–827 段(
text/12-ch02-chapter-2-fundamental-types.txt:825-827,搜「resizable buffer」)。 ↩ -
出处:「Chapter 2. Fundamental Types」第 833 段(
text/12-ch02-chapter-2-fundamental-types.txt:833,搜「read-only memory」)。 ↩ -
出处:「Chapter 2. Fundamental Types」第 815–817 段(
text/12-ch02-chapter-2-fundamental-types.txt:815-817,搜「variable-width encoding」)。 ↩ -
出处:「Chapter 2. Fundamental Types」第 835–838 段(
text/12-ch02-chapter-2-fundamental-types.txt:835-838,搜「bytes, not characters」)。 ↩↩ -
出处:「Chapter 2. Fundamental Types」第 829 段(
text/12-ch02-chapter-2-fundamental-types.txt:829,搜「invariants」)。 ↩↩ -
出处:「Chapter 2. Fundamental Types」第 897–913 段(
text/12-ch02-chapter-2-fundamental-types.txt:897-913,搜「format specifier」)。 ↩ -
出处:「Chapter 2. Fundamental Types」第 927–939 段(
text/12-ch02-chapter-2-fundamental-types.txt:927-939,搜「contains」)。 ↩ -
出处:「Chapter 2. Fundamental Types」第 840–846 段(
text/12-ch02-chapter-2-fundamental-types.txt:840-846,搜「impossible to modify」)。 ↩ -
出处:「Chapter 2. Fundamental Types」第 923 段(
text/12-ch02-chapter-2-fundamental-types.txt:923,搜「preferable to String」)。 ↩ -
出处:「Chapter 2. Fundamental Types」第 951–963 段(
text/12-ch02-chapter-2-fundamental-types.txt:951-963,搜「PathBuf」)。 ↩ -
出处:「Chapter 2. Fundamental Types」第 967–977 段(
text/12-ch02-chapter-2-fundamental-types.txt:967-977,搜「byte string」与「null-terminated」)。 ↩ -
出处:「Chapter 2. Fundamental Types」第 983–991 段(
text/12-ch02-chapter-2-fundamental-types.txt:983-991,搜「typedef」)。 ↩ -
出处:「Chapter 2. Fundamental Types」第 543–557 段(
text/12-ch02-chapter-2-fundamental-types.txt:543-557,搜「lazy_caterer」)。 ↩ -
出处:「Chapter 2. Fundamental Types」第 663–691 段(
text/12-ch02-chapter-2-fundamental-types.txt:663-691,搜「error_messages」)。 ↩ -
出处:「Chapter 2. Fundamental Types」第 726–732 段(
text/12-ch02-chapter-2-fundamental-types.txt:726-732,搜「extends past the end」)。 ↩ -
出处:「Chapter 2. Fundamental Types」第 734 段(
text/12-ch02-chapter-2-fundamental-types.txt:734,搜「for generality」)。 ↩ -
出处:「Chapter 2. Fundamental Types」第 767–795 段(
text/12-ch02-chapter-2-fundamental-types.txt:767-795,搜「escape sequences」)。 ↩ -
出处:「Chapter 2. Fundamental Types」第 752–765 段(
text/12-ch02-chapter-2-fundamental-types.txt:752-765,搜「backslash」)。 ↩ -
出处:「Chapter 2. Fundamental Types」第 797–811 段(
text/12-ch02-chapter-2-fundamental-types.txt:797-811,搜「raw string」)。 ↩ -
出处:「Chapter 2. Fundamental Types」第 967–977 段(
text/12-ch02-chapter-2-fundamental-types.txt:967-977,搜「byte string」)。 ↩ -
出处:「Chapter 2. Fundamental Types」第 897–913 段(
text/12-ch02-chapter-2-fundamental-types.txt:897-913,搜「Display」)。 ↩ -
出处:「Chapter 2. Fundamental Types」第 925–947 段(
text/12-ch02-chapter-2-fundamental-types.txt:925-947,搜「contains」)。 ↩ -
出处:「Chapter 2. Fundamental Types」第 41–165 段(
text/12-ch02-chapter-2-fundamental-types.txt:41-165,搜「Table 2-1」)。表中各行的描述与值示例取自该表。 ↩ -
出处:「Chapter 2. Fundamental Types」第 626–642 段(
text/12-ch02-chapter-2-fundamental-types.txt:626-642,搜「capacity is now」)。 ↩ -
出处:「Chapter 2. Fundamental Types」第 642 段(
text/12-ch02-chapter-2-fundamental-types.txt:642,搜「isn't guaranteed」)。 ↩ -
出处:「Chapter 2. Fundamental Types」第 644–652 段(
text/12-ch02-chapter-2-fundamental-types.txt:644-652,搜「shift all the elements」)。 ↩ -
补充(不在书里,来自通用知识):UTF-8 是变长编码,常用字符省字节;Rust 字符串底层即 UTF-8 见「Chapter 2. Fundamental Types」第 817 段(
text/12-ch02-chapter-2-fundamental-types.txt:817,搜「variable-width」)。 ↩ -
出处:「Chapter 2. Fundamental Types」第 835–838 段(
text/12-ch02-chapter-2-fundamental-types.txt:835-838,搜「bytes, not characters」)。 ↩ -
出处:「Chapter 2. Fundamental Types」第 923 段(
text/12-ch02-chapter-2-fundamental-types.txt:923,搜「preferable to String」)。 ↩ -
出处:「Chapter 2. Fundamental Types」第 819–833 段(
text/12-ch02-chapter-2-fundamental-types.txt:819-833,搜「Figure 2-3」)。 ↩