「 Rust 」数据类型

前言
Rust 是静态编译语言,在编译时必须知道所有变量的类型
- 基于使用的值,编译器通常能够推断出它的具体类型
- 但如果可能的类型比较多,例如把 String 转为整数的 parse 方法,就必须添加类型的标注,否则编译会报错
1 | fn main() { |
由于针对数字 42 在 Rust 中有很多数据类型可以将其包含在内,如 i32
和 u32
等等,所以要给变量具体指明类型,如果未指明,则会编译报错:
1 | cargo run |
标量类型
一个标量类型代表一个单个的值。
Rust 有四个主要的标量类型:
- 整数类型
- 浮点类型
- 布尔类型
- 字符类型
整数类型
整数类型没有小数部分,无符号整数类型以 u
(usize)开头,有符号整数类型以 i
(integer)开头,例如 u32 就是一个无符号的整数类型,占据 32 位的空间。
整数类型表
- 每种都分 i 和 u,以及固定的位数
- 有符号的范围是
-(2^n^ - 1) 到 2^n-1^ - 1
- 无符号范围:
0 到 2^n^ -1
Length | Signed | Unsigned |
---|---|---|
8-bit | i8 | u8 |
16-bit | i16 | u16 |
32-bit | i32 | u32 |
64-bit | i64 | u64 |
128-bit | i128 | u128 |
arch | isize | usize |
isize
和 usize
类型的位数由程序运行的计算机的架构所决定,如果是 64 位计算机,那就是 64 位的。使用场景比如,对某个集合进行索引操作。
整数字面值
Number literals | Example |
---|---|
Decimal | 98_222 |
Hex | 0xff |
Octal | 0o77 |
Binary | 0b1111_0000 |
Byte (u8 only) | b’A’ |
除了
byte
类型外,所有的数字字面值都允许使用类型后缀,例如 57u81
2
3
4
5fn main() {
// 此时,foo 的类型为 u8,值为 57
let foo = 57u8;
println!("{}", foo)
}整数的默认类型就是
i32
整数溢出
例如,u8 的范围是 0 - 255,如果把一个 u8 类型变量的值设为 256,那么:
- 调试模式下编译: Rust 会检查整数溢出,如果发生溢出,程序在运行时就会 panic
- 发布模式下编译: Rust 不会检查可能导致 panic 的整数溢出,如果发生溢出,Rust 会执行环绕操作,也就是 256 变为 1,257 变为 2,以此类推
1 | fn main() { |
cargo run
1 | cargo run |
cargo build –release
1 | ./target/release/hello-world |
浮点类型
Rust 的浮点类型使用了 IEEE-754 标准来表述,有两种基础的浮点类型,也就是含有小数部分的类型:
- f32,单精度
- f64,双精度,Rust 中默认的浮点类型
布尔类型
Rust 的布尔类型(true & false)占用 1 字节大小,符号为 bool。
字符类型
Rust 中 char
类型用来描述语言中最基础的单个字符,字符类型的字面值使用单引号,占用 4 字节的大小,是 Unicode 的标量值,可以表示比 ASCII 多得多的字符内容,如拼音,中日韩文,零长度空白字符,emoji 表情等。
范围是 U+0000 到 U+D7FF
和 U+E000
到 U+10FFFF
。
1 | fn main() { |
复合类型
复合类型可以将多个值放到一个类型里。
Rust 有两个主要的复合类型:
- 元组
- 数组
元组(Tuple)
元组可以将多个类型的多个值放到一个类型里,并且长度固定,一旦声明不可改变。
元组的类型为:(类型1,类型2,...)
访问元组中的元素值可以使用模式匹配(destructure)和点标记法。
模式匹配
1 | fn main() { |
点标记法
1 | fn main() { |
点标记法的“索引“不可以是变量。
1 | fn main() { |
1 | cargo run |
和 Python 等其他语言一样,当元组中只有一个元素,类型和值均需要加逗号,当没有逗号时,编译器会认为其是一个标量类型,括号会被视为多余。
1 | fn main() { |
数组
数组可以将多个值放到一个类型中,但是数组中每个元素的类型必须相同,并且长度固定,一旦声明不可改变。
数组的类型为:[类型;长度]
1 | fn main() { |
除了上述的声明方式外,如果数组中的每个元素值都相同,那么可以快速声明为:
1 | fn main() { |
类似于 Golang,访问数组中的元素值可以使用索引法。
索引越界
如果访问的索引超出了数组的范围,处理方式和 Golang 类似,也就是:
- 编译时会通过,但是不是绝对的,Rust 编译器无法直接判断出是否越界等较复杂的情况
- 运行时会报错,区别于 C 和 C++ 等,虽然数组在内存中为连续的地址,但是越界的内存空间不属于该数组,所以无法访问