编程语言研究书库

数值、元组与指针家族 — 基本类型(上)

数值、元组与指针家族 — 基本类型(上)

这一章讲三件事: Rust 的数值类型怎么命名、溢出时到底发生什么; 元组和单元类型 () 怎么当「最小结构体」用;以及 Rust 为什么需要一族指针类型而不是一个。 原书给这一章选的题辞是德谟克利特:「宇宙的第一原则是原子和虚空,其余皆属意见。」—— 这一章就是 Rust 宇宙的「原子」。

1. 顶层全景:类型系统的地基

  定宽数值类型(u8…u128 / i8…i128 / f32 / f64 / isize / usize)── 直接对应硬件
      │  默认推断为 i32 / f64;无隐式转换,as 显式转
      ▼
  简单复合:bool、元组 (T, U)、单元 ()
      │
      ▼
  指针家族(每个类型 = 一套内存管理策略):
    &T / &mut T(借用) · Box<T>(独占堆) · Rc/Arc(引用计数) · *const/*mut(裸指针)

图说:从「和硬件一一对应」的地基往上,每一层只做一件简单的事。

本章的主线例子是一组 u8 加法:两个 u8 相加,什么时候得到 30,什么时候溢出, 溢出时 panic、回绕、饱和、返回布尔标记四族操作各给出什么——每个机制都落在这一个加法上走一遍。

2. 数值类型:命名即规格

Rust 的整数类型命名是个正则式:u 或 i(无符号/有符号)+ 位宽。 u8 是 8 位无符号,i32 是 32 位有符号,一路排到 u128/i128; 外加两个跟机器字长走的:usize/isize(32 位机上 32 位,64 位机上 64 位,对标 C 的 size_t)1。

几个落地细节:

  • 字面量可以带后缀:42u8、1729isize;不带后缀时 Rust 先看上下文,没有任何线索就默认 i322。
  • 下划线任插:4_294_967_295、二进制 0b0101_0010——只为好看,位置无所谓3。
  • 转换必须写 as:10_i8 as u16;位不够就截断(0xcafedad_u64 as u8 只剩 0xad)4。
  • 整数有一堆方法:pow、abs、count_ones(数二进制里几个 1)、max……文档在「Primitive Type i32」词条下5。
  • 有符号数用补码(two's complement),和对应无符号类型共用同一批位模式6。

有符号类型的范围因此不对称:i8 是 −128 到 127(−2⁷ 到 2⁷−1)—— 这个不对称后面会在溢出四族操作里还一次债(−128 的绝对值表示不了)7。

为什么忍受定宽的麻烦(会溢出、会丢精度)?书里的账:它们对大多数应用够用, 而比任意精度整数、精确有理数这类表示快上千倍;真需要那种表示,num crate 有8。

字面量的全套写法

原书把整数和浮点字面量的规则讲得很细,值得一次性收齐9:

写法例子说明
十进制42、1_000_000下划线任插,只为好看
十六进制0xffff_ffff前缀 0x
八进制0o100前缀 0o
二进制0b0101_0010前缀 0b
带类型后缀42u8、127_u8、1729isize后缀直接钉死类型
字节字面量b'*'u8 值,字符必须是 ASCII

没有后缀的字面量进入「待定」状态:Rust 把它挂起,等到发现它被存进某类型、 传给某函数、和某类型的值比较——任何一个动作都能把它钉死;全程没有线索,默认 i3210。

一个会咬人的细节:负号和方法的优先级

书上专门预警了一个真实陷阱11:

println!("{}", (-4).abs());      // 4,正确
println!("{}", -4.abs());        // -4!先算 4.abs() 得 4,再取负

原因:方法调用的优先级高于一元负号。-4_i32.abs() 是 -(4_i32.abs()), 不是 (-4_i32).abs();后者想写负数的绝对值,必须加括号,或者绕开方法、用函数形式 i32::abs(-4)。 这个坑在「整数类型待定」时还会变形:(-4).abs() 若不指定类型,编译器报 「can't call method abs on ambiguous numeric type {integer}」—— 所有有符号整数都有 abs,编译器必须先定下是哪一种整数才肯调方法, 而 i32 默认值只在「所有方法调用解析完之后类型还悬着」时才生效,轮到它就太迟了12。

3. 主线例子:一次 u8 加法,四种溢出处理

u8 的范围是 0 到 255。看这两行:

assert_eq!(10_u8 + 20, 30);     // 正常:和装得下
assert_eq!(100_u8 + 200, ???);  // 300 装不下:发生什么?

默认行为分两档,而且两档都不是未定义行为——这是和 C/C++ 的分水岭:

  • debug 构建(平时开发):panic。程序带着报错信息终止13。
  • release 构建(cargo build --release):回绕(wrap)——取数学正确值对类型范围的模。300 mod 256 = 4414。

回绕在 C 里是有符号溢出的未定义行为:编译器可以假设它不发生,于是你并不知道程序会怎么死。 Rust 把这件事钉死了:要么 panic,要么按模回绕,编译器不许发挥13。

默认行为不合用时,整数类型提供四族方法,把选择写明确:

族返回什么100_u8 和 200 的结果
checked_addOption:装得下 Some(和),装不下 NoneNone
wrapping_add回绕值44(所有构建行为一致)
saturating_add「夹紧」到类型边界255
overflowing_add(结果, 是否溢出) 二元组(44, true)

checked 族最有 Rust 味:它把「可能失败」编码进 Option——上一章刚见过的类型15。 四族的完整名单:加减乘除……加减乘除都有,乘方也有;还有一族奇怪的: 移位操作查的不是结果溢出,而是移动位数超没超宽(10_u64.checked_shr(65) 是 None, 而 wrapping_shl(65) 当 65 mod 64 = 1 处理,得到 20)16。

一个有符号陷阱提前说:(-128_i8).checked_div(-1) 是 None—— −128 ÷ −1 = 128,但 i8 最大只到 127,除法也会溢出17。

各类型能装多少:两张范围表

u 系列把全部位数用来装非负数,i 系列用补码切一半给负数——完整范围(原书表 2-3、2-4)9:

无符号范围有符号范围
u80 到 255i8−128 到 127
u160 到 65,535i16−32,768 到 32,767
u320 到 4,294,967,295i32−2,147,483,648 到 2,147,483,647
u640 到 18,446,744,073,709,551,615i64±9,223,372,036,854,775,808
u1280 到约 3.4×10³⁸i128约 ±1.7×10³⁸
usize32 或 64 位机器字isize同左,带符号

u64 的上限大约是一千八百亿亿——日常计数永远用不完,但它仍是定宽,仍会回绕; u8 的 255 才是多数溢出故事的现场。

u8 就是「字节」

Rust 里字节这个角色的扮演者就是 u8——从二进制文件或网络套接字读出来的, 就是一串 u8。C 程序员要注意:Rust 没有「既能当文本又能当二进制」的单一字符类型; char 是 Unicode(全世界字符的统一编号体系)字符(4 字节),和字节完全是两回事,文本与二进制从类型上就分开了10。

usize 的另一个身份:数组下标必须是它,数组/向量长度、元素个数也都用它 (对标 C 的 size_t 与 ptrdiff_t)。64 位机器上它是 64 位;32 位机器上它是 32 位11。

debug 构建 panic 的完整例子

原书给的溢出崩溃例子短到可以背下来12:

let mut i = 1;
loop {
    i *= 10;   // debug:panic: attempt to multiply with overflow
}

debug 构建(平时开发用的)在第三次循环就 panic;release 构建则不吭声地回绕成负数, 循环永远跑下去——同一个程序,换种编译方式,从「响亮地死」变成「安静地错」。 这正是「溢出四族方法」存在的动机:默认行为分两档,要可预期就显式选18。

补码为什么范围不对称

补码的解释值得花三行:同一批比特,按无符号读是一个数,按有符号读是另一个数。 u8 的 255,二进制 1111_1111,原样当 i8 读就是 −1。所以 i8 能表示 −128(比特 1000_0000) 却表示不了 +128——正半区被 −1 这类「负数比特」吃掉了一个名额。 通用公式:iN 的范围是 −2ⁿ⁻¹ 到 2ⁿ⁻¹−1,两边永远差一19。

这个不对称在实战里的化身,就是上一节那个 (-128_i8).checked_div(-1) 返回 None: −128 的绝对值 128,i8 给不出——除法也能溢出。

整数的随身工具箱

标准库给整数挂了几十个方法,书上的示例四件套20:

assert_eq!(2_u16.pow(4), 16);           // 乘方
assert_eq!((-4_i32).abs(), 4);          // 绝对值
assert_eq!(0b101101_u8.count_ones(), 4);// 数二进制里几个 1(人口计数)
assert_eq!(12_i32.max(37), 37);         // 两个数取大

几十个方法不用背,记一个地址:在线文档搜「Primitive Type i32」, u64、f32 等也都有同名词条——想「这个类型能干什么」,先查它的词条21。

移位族:查的是距离不是结果

四族方法里移位是个异类:溢出查的不是结果,而是移动的位数。 10_u64.wrapping_shl(65) 把 65 对 64 取模当 1 处理,得 20; 10_u64.checked_shr(65) 返回 None——没有「移动 65 位」这回事。 C/C++ 里移过头是未定义行为;Rust 让你挑一种明确的行为22。

4. 浮点数与 bool:两个「例外条款」

f32/f64 是 IEEE 754 单/双精度(对标 C 的 float/double),字面量默认推断为 f64。 细节里值得带走的:浮点字面量至少得有「小数部分、指数(科学计数法里 10 的幂,如 1e6 的 6)、类型后缀」之一,否则它是整数—— 5. 是浮点,5 是整数,Rust 绝不跨派23。 特殊值有常量:f32::INFINITY、NAN、MIN、MAX24。

bool 很严格:C 里 if (x) 里的 x 可以是任何数;Rust 里 if 的条件必须是 bool, 你必须写 if x != 0;&&、|| 的两个操作数也必须是 bool25。 反向转换也一样:as 能把 bool 转成整数(true as i32 是 1),但整数不能 as 成 bool——想转就显式写比较26。 一个冷知识:bool 虽然一比特就够,内存里占一整字节——为了能给它建指针27。

浮点字面量的拼装规则

浮点字面量是一张「选配件清单」(原书配了一张语法图):整数部分之后,小数部分、 指数、类型后缀三者至少出现一个——否则它就是个整数,不会被当成浮点。 5. 是合法的浮点常量(小数部分只有一个点);1e6、3.14159f32 也都行。 没有后缀时默认 f64——和整数的默认 i32 一个思路:先问上下文,无线索用默认18。

特殊值是 IEEE 754 标准规定的,以关联常量的形式挂在类型上:f32::INFINITY(正无穷)、 NEG_INFINITY(负无穷)、NAN(不是一个数)、MIN/MAX(最大最小有限值)。 有趣的两个事实:负零是存在的,-1. / f32::INFINITY 的符号位为负; 而 -f32::MIN == f32::MAX——最小值的绝对值比最大值大 1,这和整数那侧「范围不对称」同款28。

数学常量在专门的模块里:std::f32::consts::PI、E、2 的平方根等29。

不隐式转换:再来一遍,因为这是 Rust 的脾气

第 1 章的 pixel.0 as f64 已经见过 as;这一章把原则说透: Rust 几乎不做任何隐式数值转换。函数要 f64,你递 i32 是错误; 甚至 i16 → i32 这种「每个 i16 都是合法 i32」的 widening,也要显式写 as30。

verbosity(啰嗦)是明知的代价。原书给的回报是:隐式整数转换「有导致 bug 和安全洞的 确凿前科」,尤其是当整数表示内存里某个东西的长度、而溢出悄悄发生时; 把每次转换写出来,「这个动作让我们多次发现本来会漏掉的问题」31。

5. 元组与单元:最小结构体

元组(tuple) 是「几个值的固定组合,各字段类型可以不同」:(1984_i32, false) 的类型是 (i32, bool), 字段按编号访问(t.0、t.1),不能用变量下标(t[i] 不存在)32。

元组最常见的两个用途:

  • 函数返回多个值。字符串切片的 split_at 声明是 -> (&str, &str); 接收时可以用模式 let (head, tail) = text.split_at(21) 一次拆给两个变量—— 比先接住再 .0 .1 清楚33。
  • 「别为小事发明结构体」。曼德博程序的 bounds: (usize, usize)(宽、高)就是元组: 「我们把尺寸当一个值想,而不是两个」34。

单元类型 ():零元组,只有一个值(也写作 ()),对标 C 的 void。 「没有有意义的值可带、但语法上必须有个类型」的地方用它:无返回值的函数, 或者 Result<(), Error>——「成功时无事可报,失败时报错」35。

6. 指针家族:一个类型写一套内存策略

这节回答「Rust 里指针怎么这么多」。书里给了两层原因:

第一,值是嵌套的。 Java 里对象从不物理包含另一个对象——Rectangle 里的 upperLeft 字段 只是一个指向另外创建的 Vector2D 的引用;每个对象类型骨子里都是指针类型,所以 Java 不需要指针类型。 Rust 反过来:值默认嵌套。((0, 0), (1440, 900)) 就是栈上紧挨着的四个整数,堆上什么都不分配。 省内存的代价:想让一个值指向另一个值,必须显式用指针类型说出来36。

第二,没有垃圾回收。 内存总得有人管:什么时候分配、分配多少、什么时候放。 Rust 把每一套管理策略做成一个指针类型——策略就写在类型上37:

类型策略
&T / &mut T引用:不接管所有权,只借;没有任何清理开销
Box<T>独占堆指针:Box::new(v) 分配,Box 被丢弃时释放
Rc<T> / Arc<T>引用计数:多个指针共享一个堆值,计数归零才释放;Arc 用原子计数,可跨线程
*const T / *mut T裸指针:C 指针的等价物,只能在 unsafe 块里解引用

对 C++ 读者的速查:Box 像 unique_ptr,Arc 像 shared_ptr38。

两个要点:

  • 指针非空。除裸指针外,Rust 的指针类型都没有空值;「可能没有」用 Option 表达 (Option<&T> 里的 None 当空指针用),且不花额外内存——机器层面 None 就是一个空地址39。
  • Rc/Arc 计数的分工:Rc 更快但不可跨线程,Arc 带原子操作的开销但线程安全; 不需要跨线程就用 Rc,Rust 会阻止你不小心把它传到线程边界40。

Box 的日常与裸指针的地盘

Box 不是天天用,但它是「最基础的破例」:值默认嵌套在栈上,偶尔你需要一个值明确住堆里 (比如要把它交给只认堆指针的接口,或值太大、想在几处之间只传指针)——这时 Box::new(v) 一次到位,Box 被丢弃时自动释放。它不是引用:它是主人,只是住得远41。

裸指针 *const T、*mut T 是另一回事:C 指针的原样进口,只能在 unsafe 块里解引用。 它的合法使用场景就两个:调 C 库、以及从零实现新型数据结构时绕开编译器的检查。 日常的 Rust 代码不该见到它们——见到,就意味着有人主动退出了安全保证42。

指针速查:一句话一个

类型拥有?可写?跨线程?机器字
&T否(借)否借期内容器说了算1(地址)
&mut T否(独占借)是同上1
Box<T>是(独占)可变则 Box 可变看 T1
Rc<T>是(计数共享)否否1
Arc<T>是(原子计数共享)否是1
*const/*mut T否unsafe 内手动保证1

7. 作者的判断与证据

  • **「定宽数值够用且快上千倍」**是性能主张,书没给测量,但符合业界常识(这一行公认的取舍)。
  • 「无隐式转换救过我们的命」:作者说,在 Rust 里写下转换这件事本身, 多次让他们发现了「否则会漏掉的问题」——这是经验之谈,不是数据43。
  • as 的截断规则「there are no surprises」:整数转整数总是定义良好,这是语言承诺,可验证。

8. 边界与局限

  • 浮点数的精度坑(0.1 + 0.2 ≠ 0.3 这类)原书点到即止,没有展开 IEEE 754 的舍入语义;
  • num crate(任意精度、有理数)只给了名字;
  • 裸指针只给了一段话,unsafe 全书的机制都还没放出;
  • 位运算的优先级调整(第 5 章才讲:x & BIT != 0 在 Rust 里是 (x & BIT) != 0)这一章没提。

9. 可带走的

主线例子一行版: 100_u8 + 200 → debug 构建 panic、release 回绕成 44 → checked_add 得 None、wrapping_add 得 44、saturating_add 得 255、overflowing_add 得 (44, true)。

  1. 整数命名 = u/i + 位宽;无线索时默认 i32,浮点默认 f64;
  2. 溢出:panic(调试)/ 回绕(发布),都不是未定义行为——和 C/C++ 的分水岭;
  3. 四族溢出操作:checked(给 Option)/ wrapping(给回绕值)/ saturating(夹紧)/ overflowing(带标记);
  4. 有符号范围不对称:−128 ÷ −1 会溢出,checked_div 返回 None;
  5. if 的条件必须是 bool;数字不能 as 成 bool;
  6. 元组按编号取字段、不能变量下标;函数想返回多个值就返回元组;
  7. () 是单元类型:一个值的类型,表示「这里语法上要个类型,但没什么可带的」;
  8. 值默认嵌套在栈上,堆分配必须显式要——这是指针家族存在的第一原因;
  9. 指针类型 = 内存管理策略:引用(借)、Box(独占堆)、Rc/Arc(计数)、裸指针(unsafe);
  10. 指针非空;Option<&T> 和 &T 一样大,None 在机器层面就是空地址。

10. 原文地图

主题原书章原文位置
类型推断与动态语言的对比Chapter 2. Fundamental Typestext/12-ch02-chapter-2-fundamental-types.txt:39(搜「Type inference」)
定宽类型快上千倍Chapter 2. Fundamental Typestext/12-ch02-chapter-2-fundamental-types.txt:181(搜「thousands of times faster」)
数值命名与机器字Chapter 2. Fundamental Typestext/12-ch02-chapter-2-fundamental-types.txt:218(搜「machine word」)
字面量后缀与 i32 默认Chapter 2. Fundamental Typestext/12-ch02-chapter-2-fundamental-types.txt:278(搜「defaults to i32」)
下划线与 as 转换Chapter 2. Fundamental Typestext/12-ch02-chapter-2-fundamental-types.txt:284(搜「as operator」)
补码与不对称范围Chapter 2. Fundamental Typestext/12-ch02-chapter-2-fundamental-types.txt:247(搜「two’s complement」)
溢出默认行为Chapter 2. Fundamental Typestext/12-ch02-chapter-2-fundamental-types.txt:315(搜「overflow」)
四族溢出操作Chapter 2. Fundamental Typestext/12-ch02-chapter-2-fundamental-types.txt:337(搜「Checked operations」) · text/12-ch02-chapter-2-fundamental-types.txt:352(搜「Wrapping operations」) · text/12-ch02-chapter-2-fundamental-types.txt:364(搜「Saturating operations」) · text/12-ch02-chapter-2-fundamental-types.txt:369(搜「Overflowing operations」)
除法溢出特例Chapter 2. Fundamental Typestext/12-ch02-chapter-2-fundamental-types.txt:350(搜「checked_div」)
移位检查的是位数Chapter 2. Fundamental Typestext/12-ch02-chapter-2-fundamental-types.txt:374(搜「shift distance」)
bool 的严格性Chapter 2. Fundamental Typestext/12-ch02-chapter-2-fundamental-types.txt:434(搜「require their conditions」)
元组与多值返回Chapter 2. Fundamental Typestext/12-ch02-chapter-2-fundamental-types.txt:447(搜「n-tuple」)
单元类型Chapter 2. Fundamental Typestext/12-ch02-chapter-2-fundamental-types.txt:485(搜「unit type」)
值默认嵌套、堆上无分配Chapter 2. Fundamental Typestext/12-ch02-chapter-2-fundamental-types.txt:503(搜「four adjacent integers」)
指针家族与策略Chapter 2. Fundamental Typestext/12-ch02-chapter-2-fundamental-types.txt:505(搜「memory management policies」)
Rc/Arc 分工Chapter 2. Fundamental Typestext/12-ch02-chapter-2-fundamental-types.txt:511(搜「atomic reference count」)
指针非空Chapter 2. Fundamental Typestext/12-ch02-chapter-2-fundamental-types.txt:519(搜「non-nullable」)
字面量全套写法Chapter 2. Fundamental Typestext/12-ch02-chapter-2-fundamental-types.txt:280(搜「prefixes」)
负号与方法优先级陷阱Chapter 2. Fundamental Typestext/12-ch02-chapter-2-fundamental-types.txt:311(搜「higher precedence」)
浮点字面量与特殊值Chapter 2. Fundamental Typestext/12-ch02-chapter-2-fundamental-types.txt:401(搜「at least one」) · text/12-ch02-chapter-2-fundamental-types.txt:407(搜「INFINITY」)
两张范围表Chapter 2. Fundamental Typestext/12-ch02-chapter-2-fundamental-types.txt:230(搜「0 to 28」)
u8 是字节、usize 是下标Chapter 2. Fundamental Typestext/12-ch02-chapter-2-fundamental-types.txt:274(搜「binary data」)
溢出 panic 的完整例子Chapter 2. Fundamental Typestext/12-ch02-chapter-2-fundamental-types.txt:325(搜「wraps to a negative」)
补码不对称与整数工具箱Chapter 2. Fundamental Typestext/12-ch02-chapter-2-fundamental-types.txt:247(搜「two’s complement」) · text/12-ch02-chapter-2-fundamental-types.txt:293(搜「count_ones」)
移位族查距离Chapter 2. Fundamental Typestext/12-ch02-chapter-2-fundamental-types.txt:374(搜「shift distance」)
Box 的日常与裸指针地盘Chapter 2. Fundamental Typestext/12-ch02-chapter-2-fundamental-types.txt:509(搜「override the default nesting」) · text/12-ch02-chapter-2-fundamental-types.txt:513(搜「unsafe blocks」)
隐式转换的教训Chapter 2. Fundamental Typestext/12-ch02-chapter-2-fundamental-types.txt:426(搜「alerted us to problems」)

Footnotes

  1. 出处:「Chapter 2. Fundamental Types」第 218 段(text/12-ch02-chapter-2-fundamental-types.txt:218,搜「machine word」)。 ↩

  2. 出处:「Chapter 2. Fundamental Types」第 278 段(text/12-ch02-chapter-2-fundamental-types.txt:278,搜「defaults to i32」)。 ↩

  3. 出处:「Chapter 2. Fundamental Types」第 282 段(text/12-ch02-chapter-2-fundamental-types.txt:282,搜「underscores」)。 ↩

  4. 出处:「Chapter 2. Fundamental Types」第 284–287 段(text/12-ch02-chapter-2-fundamental-types.txt:284-287,搜「truncated」)。 ↩

  5. 出处:「Chapter 2. Fundamental Types」第 291–296 段(text/12-ch02-chapter-2-fundamental-types.txt:291-296,搜「count_ones」)。 ↩

  6. 出处:「Chapter 2. Fundamental Types」第 247 段(text/12-ch02-chapter-2-fundamental-types.txt:247,搜「two’s complement」)。 ↩

  7. 出处:「Chapter 2. Fundamental Types」第 255–256 段(text/12-ch02-chapter-2-fundamental-types.txt:255-256,搜「−128 to 127」)。 ↩

  8. 出处:「Chapter 2. Fundamental Types」第 181 段(text/12-ch02-chapter-2-fundamental-types.txt:181,搜「thousands of times faster」)。 ↩

  9. 出处:「Chapter 2. Fundamental Types」第 278–287 段(text/12-ch02-chapter-2-fundamental-types.txt:278-287,搜「0x」)。 ↩ ↩2

  10. 出处:「Chapter 2. Fundamental Types」第 278 段(text/12-ch02-chapter-2-fundamental-types.txt:278,搜「puts off determining」)。 ↩ ↩2

  11. 出处:「Chapter 2. Fundamental Types」第 311 段(text/12-ch02-chapter-2-fundamental-types.txt:311,搜「higher precedence」)。 ↩ ↩2

  12. 出处:「Chapter 2. Fundamental Types」第 298–311 段(text/12-ch02-chapter-2-fundamental-types.txt:298-311,搜「ambiguous numeric type」)。 ↩ ↩2

  13. 出处:「Chapter 2. Fundamental Types」第 315 段(text/12-ch02-chapter-2-fundamental-types.txt:315,搜「overflow」)。「在两种情形下溢出都不是未定义行为,不像 C/C++ 的有符号整数。」 ↩ ↩2

  14. 出处:「Chapter 2. Fundamental Types」第 315、325 段(text/12-ch02-chapter-2-fundamental-types.txt:315-325,搜「wraps around」与「wraps to a negative number」)。 ↩

  15. 出处:「Chapter 2. Fundamental Types」第 337 段(text/12-ch02-chapter-2-fundamental-types.txt:337,搜「Checked operations」)。 ↩

  16. 出处:「Chapter 2. Fundamental Types」第 374–377 段(text/12-ch02-chapter-2-fundamental-types.txt:374-377,搜「shift distance」)。 ↩

  17. 出处:「Chapter 2. Fundamental Types」第 349–350 段(text/12-ch02-chapter-2-fundamental-types.txt:349-350,搜「checked_div」)。 ↩

  18. 出处:「Chapter 2. Fundamental Types」第 397–405 段(text/12-ch02-chapter-2-fundamental-types.txt:397-405,搜「lone decimal point」)。 ↩ ↩2

  19. 出处:「Chapter 2. Fundamental Types」第 247–256 段(text/12-ch02-chapter-2-fundamental-types.txt:247-256,搜「two’s complement」)。「用与对应无符号类型相同的比特,铺满正负两段」。 ↩

  20. 出处:「Chapter 2. Fundamental Types」第 291–296 段(text/12-ch02-chapter-2-fundamental-types.txt:291-296,搜「count_ones」)。 ↩

  21. 出处:「Chapter 2. Fundamental Types」第 296 段(text/12-ch02-chapter-2-fundamental-types.txt:296,搜「dozens」)。 ↩

  22. 出处:「Chapter 2. Fundamental Types」第 374–377 段(text/12-ch02-chapter-2-fundamental-types.txt:374-377,搜「wrapping_shl」)。 ↩

  23. 出处:「Chapter 2. Fundamental Types」第 401 段(text/12-ch02-chapter-2-fundamental-types.txt:401,搜「at least one」)。 ↩

  24. 出处:「Chapter 2. Fundamental Types」第 407 段(text/12-ch02-chapter-2-fundamental-types.txt:407,搜「INFINITY」)。 ↩

  25. 出处:「Chapter 2. Fundamental Types」第 434 段(text/12-ch02-chapter-2-fundamental-types.txt:434,搜「require their conditions」)。 ↩

  26. 出处:「Chapter 2. Fundamental Types」第 436–441 段(text/12-ch02-chapter-2-fundamental-types.txt:436-441,搜「won’t convert in the other direction」)。 ↩

  27. 出处:「Chapter 2. Fundamental Types」第 443 段(text/12-ch02-chapter-2-fundamental-types.txt:443,搜「entire byte」)。 ↩

  28. 出处:「Chapter 2. Fundamental Types」第 407–415 段(text/12-ch02-chapter-2-fundamental-types.txt:407-415,搜「is_sign_negative」)。 ↩

  29. 出处:「Chapter 2. Fundamental Types」第 417 段(text/12-ch02-chapter-2-fundamental-types.txt:417,搜「consts」)。 ↩

  30. 出处:「Chapter 2. Fundamental Types」第 424 段(text/12-ch02-chapter-2-fundamental-types.txt:424,搜「almost no numeric conversions」)。 ↩

  31. 出处:「Chapter 2. Fundamental Types」第 426 段(text/12-ch02-chapter-2-fundamental-types.txt:426,搜「alerted us to problems」)。 ↩

  32. 出处:「Chapter 2. Fundamental Types」第 447–449 段(text/12-ch02-chapter-2-fundamental-types.txt:447-449,搜「n-tuple」)。 ↩

  33. 出处:「Chapter 2. Fundamental Types」第 451–460 段(text/12-ch02-chapter-2-fundamental-types.txt:451-460,搜「split_at」)。 ↩

  34. 出处:「Chapter 2. Fundamental Types」第 483 段(text/12-ch02-chapter-2-fundamental-types.txt:483,搜「one value, not two」)。 ↩

  35. 出处:「Chapter 2. Fundamental Types」第 485–495 段(text/12-ch02-chapter-2-fundamental-types.txt:485-495,搜「unit type」)。 ↩

  36. 出处:「Chapter 2. Fundamental Types」第 503 段(text/12-ch02-chapter-2-fundamental-types.txt:503,搜「four adjacent integers」)。 ↩

  37. 出处:「Chapter 2. Fundamental Types」第 505 段(text/12-ch02-chapter-2-fundamental-types.txt:505,搜「memory management policies」)。 ↩

  38. 出处:「Chapter 2. Fundamental Types」第 517 段(text/12-ch02-chapter-2-fundamental-types.txt:517,搜「smart pointer」)。 ↩

  39. 出处:「Chapter 2. Fundamental Types」第 519 段(text/12-ch02-chapter-2-fundamental-types.txt:519,搜「non-nullable」)。 ↩

  40. 出处:「Chapter 2. Fundamental Types」第 511 段(text/12-ch02-chapter-2-fundamental-types.txt:511,搜「atomic reference count」)。 ↩

  41. 出处:「Chapter 2. Fundamental Types」第 509 段(text/12-ch02-chapter-2-fundamental-types.txt:509,搜「override the default nesting」)。 ↩

  42. 出处:「Chapter 2. Fundamental Types」第 513 段(text/12-ch02-chapter-2-fundamental-types.txt:513,搜「unsafe blocks」)。 ↩

  43. 出处:「Chapter 2. Fundamental Types」第 426 段(text/12-ch02-chapter-2-fundamental-types.txt:426,搜「alerted us to problems」)。 ↩

On this page