Rust初学
Rust基础学习
变量绑定与解构
变量绑定:let a = "hello word"
不可变变量声明:let a = "hello word"
可变变量声明:let mut x =5
未使用变量声明:let _y = 6
变量解构:let (a, mut b): (bool, bool) = (true, false)
变量遮蔽(shadowing):在后面声明的变量会遮蔽掉前面声明的,如下:
1 | fn main() { |
简而言之,变量遮蔽就是在不同的作用域中可以声明相同变量名的变量。
基本数据类型
无外乎那么几种类型,但是注意,在Rust语言中,我们需要显式地基于变量一个类型,否则编译器将自动推导。
这里整理一份基本类型的表:
数值类型
整数类型:
长度 | 有符号类型 | 无符号类型 |
---|---|---|
8 | i8 | u8 |
16 | i16 | u16 |
32 | i32 | u32 |
64 | i64 | u64 |
128 | i128 | u128 |
视架构而定 | isize | usize |
类型定义的统一形式为:有无符号+类型大小
,无符号数(unsigned)表示数字只能取0和正数,范围在0~2^n-1
,有符号(integer)标识数字可取正数、负数和0,范围在-(2^(n-1)~2^(n-1)-1)
。
并且,在rust中规定的字面量表示方法:
数字字面量 | 示例 |
---|---|
十进制 | 98_222 |
十六进制 | 0xff |
八进制 | 0o77 |
二进制 | 0b1111_0000 |
字节(仅限于u8) | b’A’ |
rust整型默认使用i32
。
显式处理可能出现整型溢出的方法:
- 使用
wrapping_*
方法在所有模式下都按照补码循环溢出的规则处理。 - 如果使用
checked_*
方法是发生溢出,则返回None
值 - 使用
overflowing_*
方法返回该值和一个指示是否存在溢出的布尔值。 - 使用
saturating_*
方法,可以限定计算后的结果不超过目标类型的最大值或低于最小值。
浮点类型:
浮点类型,zairust中使用(单精度浮点型)f32
和(双精度浮点型)f64
来表示,默认浮点类型为f64
。
浮点数陷阱:
浮点数由于底层格式的特殊性,导致了如果在使用浮点数时不够谨慎,就可能造成危险,有两个原因:
- 浮点数往往是一个确切数字的近似表达,浮点数类型是基于二进制实现的,但是计算的数字往往是基于十进制的,例如
0,1
在二进制上并不存在精确的表达形式,但是在十进制上就存在。这种不匹配性导致一定的歧义性,更多的,虽然浮点数能代表真实的数值,但是由于底层格式问题,它往往受限于定长的浮点数精度,如果想要表达完全精准的真实数字,只有使用无限精度的浮点数才行。 - 浮点数在某些特性上是反直觉的 例如大家都会觉得浮点数可以进行比较,一般情况下,确实可以使用
< > => = <=
进行比较,但是在某些场景下,这种直觉上的比较特性反而会害了你。因为f32
,f64
上的比较运算实现的是std::cmp::PartialEq
特征(类似其他语言的接口),但是并没有实现std::cmp::Eq
特征,但是后者在其他数值类型上都有定义。比如说:
Rust
的HashMap
数据结构,是一个KV类型的Hash Map实现,它对于k
没有特定类型的限制,但是要求能用作k
的类型必需实现了std::cmp::Eq
特征,因此这意味着你无法使用浮点数作为HashMap
的key
,来存储键值对,但是作为对比,Rust的整数类型、字符串类型、布尔类型都实现了该特征,因此可以作为HashMap
的key
。
为了避免上面说的两个陷阱,你需要遵守以下准则:
- 避免在浮点数上测试相等性。
- 当结果在数学上可能存在未定义时,需要格外的小心。
Rust的浮点数类型使用NaN(not a number)
来处理数学上未定义的结果。并且所有跟NaN
交互的操作,都会返回一个NaN
,而且NaN
不能用来比较。并且,可以使用is_nan()
等方法,来判断一个数值是否是NaN
。
数学运算:
来看一个综合性的示例:
1 | fn main() { |
位运算:
与其他语言类似
运算符 | 说明 |
---|---|
&位与 | 相同位置均为1时则为1,否则为0 |
|位或 | 相同位置只要有1则为1,否则为0 |
^异或 | 相同位置不相同则为1, 相同则为0 |
!位非 | 把位中的0和1相互取反,即0置为1,1置为0 |
<<左移 | 所有位向左移动指定位数,右位补0 |
>>右移 | 所有位向右移动指定位数,带符号移动(正数补0,负数补1) |
评论