Rust是一种系统级编程语言,注重速度、内存安全和并行性。它提供了丰富的数据类型体系,可以分为两大类:标量(scalar)类型和复合(compound)类型。
标量类型
-
整数类型:Rust提供多种大小的有符号和无符号整数类型。例如,
i8
,i16
,i32
,i64
,i128
分别表示8位、16位、32位、64位和128位的有符号整数;u8
,u16
,u32
,u64
,u128
表示相应的无符号整数。 -
浮点类型:Rust支持两种主要的浮点数类型,
f32
和f64
,分别代表32位和64位浮点数。 -
布尔类型:布尔类型只有一个关键字
bool
,它可以有两个值:true
和false
。 -
字符类型:Rust的
char
类型用于表示单个Unicode字符,不仅限于ASCII。
复合类型
-
元组(Tuple):允许将多个不同类型的值组合在一起。可以通过模式匹配或使用
.
操作符后跟索引来访问元组中的元素。 -
数组(Array):一个固定大小的相同类型元素集合。数组的所有元素必须是同一类型。定义方式为
[type; size]
。 -
向量(Vector):与数组类似,但可以在运行时改变大小。它是通过标准库中的
Vec<T>
类型实现的,提供了动态调整大小的功能。
除了上述基本类型之外,Rust还允许通过结构体(structs)、枚举(enums)等自定义复杂的数据类型,并且支持使用泛型来编写更加通用和可重用的代码。
一、标量类型(Scalar Types)
标量类型表示单个值,包括整数、浮点数、布尔值和字符。
1. 整数类型(Integers)
特点:
- 有符号(
i
开头)和无符号(u
开头)两种类型。 - 支持多种位数:
i8/u8
,i16/u16
,i32/u32
,i64/u64
,i128/u128
。 - 默认类型:
i32
(32位有符号整数)和u32
(32位无符号整数)。
示例代码:
rust
fn main() {
// 显式类型标注
let signed: i32 = 42; // 有符号整数(默认i32)
let unsigned: u8 = 255; // 无符号整数(u8最大值255)
// 类型推断(无需显式标注)
let default_int = 100; // 推断为i32
let default_uint = 100u8; // 显式标注u8
// 溢出检查(编译时报错)
// let overflow = 256u8; // 错误:超过u8的范围(0-255)
}
下表显示了Rust 中的内置的整数类型:
长度 | 有符号类型 | 无符号类型 |
---|---|---|
8 位 | i8 | u8 |
16 位 | i16 | u16 |
32 位 | i32 | u32 |
64 位 | i64 | u64 |
128 位 | i128 | u128 |
视架构而定 | isize | usize |
每个有符号类型规定的数字范围是 -(2n - 1) ~ 2n - 1 - 1,其中 n 是该定义形式的位长度。因此 i8 可存储数字范围是 -(27) ~ 27 - 1,即 -128 ~ 127。无符号类型可以存储的数字范围是 0 ~ 2n - 1,所以 u8 能够存储的数字为 0 ~ 28 - 1,即 0 ~ 255。
此外,isize 和 usize 类型取决于程序运行的计算机 CPU 类型: 若 CPU 是 32 位的,则这两个类型是 32 位的,同理,若 CPU 是 64 位,那么它们则是 64 位。
注意事项:
- 溢出检查:Rust在编译时会检查常量是否超出类型范围。
- 选择类型:根据数值范围选择合适位数(如
u8
适合0-255的计数器)。
2. 浮点类型(Floats)
特点:
- 支持两种精度:
f32
(32位单精度)和f64
(64位双精度)。 - 默认类型:
f64
。
示例代码:
rust
fn main() {
let single_precision: f32 = 3.14; // 显式f32
let double_precision = 2.71828; // 推断为f64
// 科学计数法
let scientific = 6.022e23; // 6.022 × 10^23
}
注意事项:
- 精度问题:浮点数计算可能有微小误差(如
0.1 + 0.2 != 0.3
)。 - 避免在浮点数上测试相等性
- 选择类型:
f32
适合对内存敏感的场景(如游戏开发),f64
适合需要高精度的场景。
例如,下列代码会崩溃:
rust
// assertion failed: 0.1 + 0.2 == 0.3
fn main() {
// 断言0.1 + 0.2与0.3相等
assert!(0.1 + 0.2 == 0.3);
}
3. 布尔类型(Booleans)
特点:
- 只有两个值:
true
和false
。 - 类型为
bool
。
示例代码:
rust
fn main() {
let is_rust_amazing = true;
let is_rust_easy = false;
// 逻辑运算
let and_result = is_rust_amazing && is_rust_easy; // false
let or_result = is_rust_amazing || is_rust_easy; // true
let not_result = !is_rust_amazing; // false
}
注意事项:
- 短路运算:
&&
和||
会短路(若前一个条件已确定结果,后续条件不执行)。
4. 字符类型(Chars)
特点:
- 表示单个Unicode标量值,占4字节。
- 使用单引号
'
包裹,支持表情符号、中文等。
示例代码:
rust
fn main() {
let letter = 'A'; // ASCII字符
let emoji = '🎉'; // Unicode字符
let chinese = '你'; // 中文字符
// 转义字符
let tab = '\t'; // 制表符
let newline = '\n'; // 换行符
let heart = '\u{2665}'; // Unicode代码点(♥)
}
注意事项:
- 编码要求:字符和字符串必须使用UTF-8编码,否则编译报错。
- ASCII优化:若仅需ASCII字符,可用
u8
类型(1字节)并用b'A'
表示。
二、复合类型(Compound Types)
复合类型由多个值组合而成,包括元组(Tuple)和数组(Array)。
1. 元组(Tuples)
特点:
- 固定长度,元素类型可以不同。
- 通过索引(
.0
,.1
等)或解构访问元素。
示例代码:
rust
fn main() {
// 声明元组
let tuple = (500, 6.4, 'R'); // 类型为(i32, f64, char)
// 解构元组
let (x, y, z) = tuple;
println!("x = {}, y = {}, z = {}", x, y, z); // x = 500, y = 6.4, z = R
// 索引访问
println!("First element: {}", tuple.0); // 500
// 单元素元组(注意逗号)
let single = (42,); // 类型为(i32,)
}
注意事项:
- 单位类型:空元组
()
表示无值,常用于函数返回。 - 不可变性:元组元素不可变(除非显式使用
mut
)。
2. 数组(Arrays)
特点:
- 固定长度,所有元素类型相同。
- 通过方括号
[]
声明,支持三种初始化方式。
示例代码:
rust
fn main() {
// 方式1:推断类型和长度
let arr1 = [1, 2, 3, 4]; // 类型为[i32; 4]
// 方式2:显式类型和长度
let arr2: [f64; 3] = [0.1, 0.2, 0.3];
// 方式3:重复元素
let arr3 = [true; 5]; // [true, true, true, true, true]
// 访问元素
println!("Third element: {}", arr1[2]); // 3(索引从0开始)
// 数组长度
println!("Length: {}", arr1.len()); // 4
}
注意事项:
- 长度固定:无法动态扩容,需改用
Vec<T>
(向量,标准库类型)。 - 索引越界:运行时会panic(如
arr[4]
在长度为3的数组中会报错)。
三、常见问题与最佳实践
1. 类型推断与显式标注
- 类型推断:Rust会根据赋值自动推断类型(如
let x = 5;
推断为i32
)。 - 显式标注:当类型不明确时需显式标注:rust
let answer: u32 = "42".parse().expect("Not a number!");
2. 运算符
- 算术运算:
+
,-
,*
,/
,%
。 - 复合赋值:
+=
,-=
,*=
,/=
(如x += 1
等价于x = x + 1
)。 - 无
++
和--
:Rust不支持,避免代码歧义。
3. 编码与内存
- 字符编码:所有字符串和字符必须为UTF-8。
- 内存优化:选择合适类型(如
u8
代替char
存储ASCII字符)。
四、练习与验证
练习1:数据类型转换
rust
fn main() {
let decimal = 68.42_f32; // 显式标注f32类型
let integer = decimal as u8; // 转换为u8(截断为68)
println!("Converted to u8: {}", integer);
}
练习2:元组与数组嵌套
rust
fn main() {
// 嵌套元组和数组
let complex_tuple = ([1, 2], (true, 'A'));
println!("First element of array: {}", complex_tuple.0[0]); // 1
}