DIVE INTO RUST LAKE

[0] 前言

[1] 数据类型

Rust 的数值类型和运算跟其他语言较为相似,但是实际上,除了语法上的不同之外,还是存在一些差异点:

  1. Rust 拥有相当多的数值类型. 因此你需要熟悉这些类型所占用的字节数,这样就知道该类型允许的大小范围以及你选择的类型是否能表达负数

  2. 类型转换必须是显式的. Rust 永远也不会偷偷把你的 16bit 整数转换成 32bit 整数

  3. Rust 的数值上可以使用方法. 例如你可以用以下方法来将 13.14 取整:13.14_f32.round(),在这里我们使用了类型后缀,因为编译器需要知道 13.14 的具体类型

[1-1] 整数类型

与 C++ 几乎没有差别,只是溢出在 debug 模式下会默认抛出错误,在 release 模式下会默认正常。开发者可以通过标准库里的一些函数来强制定义函数行为,具体请见[0xFF]部分的“处理溢出”

[1-2] 浮点数

浮点数会有精度损失的问题,因此避免在浮点数上测试相等性,如果非要比较也请用容忍误差的不等式来处理;当结果在数学上可能存在UB的时候,也要防御性编程,Rust 将未定义的数学表达式的返回值设置成 NaN

[1-3] 字符、单元

Unicode 字符,占4字节

()被称为单元类型,唯一的值也是(). 比如 main() 函数返回的就是 () 这个值. () 可以作为一个值用来占位,但是完全不占用任何内存。

[1-4] 类型转换、有理数与复数

请见Rust 语言圣经相关内容

[1-5] 语句、表达式与函数

目前可以理解为,语句没有返回值而表达式有返回值。函数如果没有显式定义返回值的话,默认返回单元类型(也就是说 fn main() {} 与 fn main() -> () {} 是等价的)。

常见的语句有:let

常见的表达式有:if-else结构

至于函数,需要注意的点是:①函数可以在任意位置声明,不需要在使用的代码上面声明 ②函数是一个表达式 ③发散函数,用到的时候点这里

[2] 格式化输出

[2-1] println! 宏

1
2
3
4
5
6
7
8
println!("{:.2}", x);  // 控制小数位为2位
println!("{:08b}", x); // 左高右低输出二进制01,不足8位高位补0
println!("{:.2}", x); //
println!("{:.2}", x); //
println!("{:.2}", x); //
println!("{:.2}", x); //
println!("{:.2}", x); //
println!("{:.2}", x); //

[3] 所有权

[3-1] 变量的绑定与解构

let, let mut, let (mut a, b) = (1, 2), let [c, .., d, _] = [1, 2, 3, 4, 5], let e; Struct {e, ..} = Struct {e: 5};

[3-2] 所有权

[0xFF] Rust 的标准库

[F-0] 常见与未分类

1
std::mem::size_of_val(&x) // 某个数据类型的大小

[F-1] 处理溢出

使用 wrapping_* 方法在所有模式下都按照补码循环溢出规则处理,例如 wrapping_add

如果使用 checked_* 方法时发生溢出,则返回 None 值

使用 overflowing_* 方法返回该值和一个指示是否存在溢出的布尔值

使用 saturating_* 方法,可以限定计算后的结果不超过目标类型的最大值或低于最小值,例如:

[F-2]