参考:https://kaisery.github.io/trpl-zh-cn/ch03-02-data-types.html、https://doc.rust-lang.org/book/ch03-02-data-types.html
除了原生数据类型之外,还可以自定义数据类型:struct、enum;以及可以定义常量:const、static。
这里的原生数据类型都是存储在栈上的,并且当离开作用域时被移出栈。
标量 (scalar)
整型 (int)
- 从类型和范围看:
| 长度 | 有符号 | 范围 | 无符号 | 范围 |
| —- | —- | —- | —- | —- |
| 8-bit |
i8| -128 ~ 127 |u8| 0 ~ 255 | | 16-bit |i16| -32,768 ~ 32,767 (约正负 3 万,3E4) |u16| 0 ~ 65,536 (约 6 万,6E4) | | 32-bit |i32| -2,147,483,648 ~ 2,147,483,647
(约正负 21 亿,2E9) |u32| 0 ~ 4,294,967,296 (约 42 亿,4E9) | | 64-bit |i64| ±9.2E18 |u64| 0 ~ 1.8E19 | | 128-bit |i128| ±1.7E38 |u128| 0 ~ 3.4E38 | | arch |isize| 依赖运行程序的计算机架构:64 或 32 位 |usize| 64 或 32 位 |
每一个有符号的变体可以储存包含从 到 $ 2^{n - 1} - 1$ 在内的数字,这里 n 是变体使用的位数。所以 i8 可以储存从 -(2^7 ) 到 2^7 - 1 在内的数字,也就是从 -128 到 127。无符号的变体可以储存从 0 到 的数字,所以 u8 可以储存从 0 到 2^8 - 1 的数字,也就是从 0 到 255。
- 从输入的形式看:
| 数字字面值 | 例子 |
| —- | —- |
| Decimal (十进制) |
98_222| | Hex (十六进制) |0xff| | Octal (八进制) |0o77| | Binary (二进制) |0b1111_0000| | Byte (单字节字符)(仅限于u8) |b'A'|
除 byte 以外的所有数字字面值允许使用类型后缀,例如 57u8、57f64;同时也允许使用 _ 做为分隔符以方便读数,例如1_000。
- Rust 的默认整型是
**i32**:它通常是最快的,甚至在 64 位系统上也是。isize或usize主要作为某些集合的索引。 - 整型溢出:Rust Book: data-types | integer-overflow
在 debug 模式编译时,Rust 检查这类问题并使程序 panic (程序因错误而退出)。
在 release 构建中,Rust 不检测溢出,相反会进行一种被称为二进制补码包装(two’s complement wrapping )的操作:256 变成 0,257 变成 1,依此类推。
依赖整型溢出被认为是一种错误,即便可能出现这种行为。如果你确实需要这种行为,标准库中有一个类型显式提供此功能,Wrapping。
浮点型 (float)
f32 和 f64,分别占 32 位和 64 位。
默认类型是 **f64** ,因为在现代 CPU 中,它与 f32 速度几乎一样,不过精度更高。
注意:Rust 中的浮点型必须带小数点 .,比如 1 是默认 i32,而 1. 默认才是 f64。在基础的加减乘除中,运算符号前后必须是同一类型,如 1+1. 是不允许的。
布尔型 (bool)
字符型 (char)
Rust 的 char 类型由 **'** (单引号)指定,大小为四个字节 (4 bytes),并代表了一个 Unicode 标量值(Unicode Scalar Value),这意味着它可以比 ASCII 表示更多内容。
拼音字母(Accented letters)、单个数字 0-9、中文、日文、韩文等字符,emoji(绘文字)以及零长度的空白字符都是有效的 char 值。
Unicode 标量值包含从U+0000到U+D7FF和U+E000到U+10FFFF 在内的值。
字符串字面值(str)
Rust 的 str 类型由 **"** (双引号)指定,全称为 string literals,是被硬编码进程序里的字符串值,编译后被储存在二进制文件中,是不可(在程序运行时)变的。
硬编码 是指将可变变量用一个固定值来代替的方法,将数据直接嵌入到程序或其他可执行对象的源代码中,不同于从外部获取数据或在运行时生成数据。 硬编码数据通常只能通过编辑源代码和重新编译可执行文件来修改,尽管可以使用调试器或十六进制编辑器在内存或磁盘上进行更改。
在编译时就知道其内容,所以文本被直接硬编码进最终的可执行文件中。这使得字符串字面值快速且高效。
Rust 的核心语言中只有一种字符串类型:str,即字符串 slice,它通常以被借用的形式出现,&str。而字符串 slice 是一些储存在别处的 UTF-8 编码字符串数据的引用。比如字符串字面值被储存在程序的二进制输出中,字符串 slice 也是如此。
另一种可变的 类型:”String”
复合 (compound)
元组 (tuple)
元组是将多个其他类型的值用 ( ) 和 , 组合起来。元组在栈上不一定是连续存储的,也无法遍历 (traverse or iterate) 元组。
元组长度是固定的:一旦声明,其长度不会增大或缩小。
定义与索引:
let tup: (i32, f64, u8) = (500, 6.4, 1); // 定义元组数据let tup = (500, 6.4, 1); // 类型注解不是必要的let (x, y, z) = tup; // 使用模式匹配(pattern matching)来解构(destructure)元组值// 或者使用点号 `.` 后跟值的索引来直接访问,元组的第一个索引值是 0;如果超出索引会 paniclet five_hundred = x.0;let six_point_four = x.1;let one = x.2;
元组的一些特殊情况:
()是 unit 类型,属于标量类型,通常作为语句(比如表达式;)的值,或者函数未标注返回值类型时默认的返回值(single_element,)和(literal)是不同的类型,前者表示 单元素元组,后者表示 括号中的字面值(类比在表达式外层加括号其实就是指表达式本身:(1+1)和1+1是一样的)// 创建单元素元组需要一个额外的逗号,这是为了和被括号包含的字面量作区分。println!("one element tuple: {:?}", (5u32,));println!("just an integer: {:?}", (5u32)); // 加括号的原因是这个值的描述比较多,把括号里面的内容作为整体,而不是作为元组的元素
数组 (array)
数组是将相同类型的值用[]组合起来。
数组的长度是固定的:一旦声明,其长度不会增大或缩小。
数组每个元素的类型必须相同。
数组是一整块分配在栈上的连续存储的内存。可以遍历 (traverse or iterate) 数组。
定义与索引:
越界访问会let a: [i32; 5] = [1, 2, 3, 4, 5]; // 定义数组,与元组类似let a = [1, 2, 3, 4, 5]; // 类型注解不是必要的let a = [3; 5]; // 由于是数组元素是单一的类型,所以可以使用 `[初始值;个数]` 来生成一组元素相同的数组let a = [3, 3, 3, 3, 3]; // 这个与上面一条等价let a: [i32; 5] = [3; 5]; // `[初始值;个数]` 的形式也可用在类型注解上
panic。切片 (slice)
“slice”
打印结果:// 数组与 slice 的例子use std::mem;// 此函数借用一个 slicefn analyze_slice(slice: &[i32]) {println!("first element of the slice: {}", slice[0]);println!("the slice has {} elements", slice.len());}fn main() {// 定长数组(类型标记是多余的)let xs: [i32; 5] = [1, 2, 3, 4, 5];// 所有元素可以初始化成相同的值let ys: [i32; 500] = [0; 500];// 下标从 0 开始println!("first element of the array: {}", xs[0]);println!("second element of the array: {}", xs[1]);// `len` 返回数组的大小println!("array size: {}", xs.len());// 数组是在栈中分配的println!("array occupies {} bytes", mem::size_of_val(&xs));// 数组可以自动被借用成为 sliceprintln!("borrow the whole array as a slice");analyze_slice(&xs);// slice 可以指向数组的一部分println!("borrow a section of the array as a slice");analyze_slice(&ys[1 .. 4]);// 越界的下标会引发致命错误(panic)// println!("{}", xs[5]);}
first element of the array: 1second element of the array: 2array size: 5array occupies 20 bytesborrow the whole array as a slicefirst element of the slice: 1the slice has 5 elementsborrow a section of the array as a slicefirst element of the slice: 0the slice has 3 elements
