Rust 数据类型
Rust 是一门静态类型语言,数据类型在编译时必须明确,编译器通过类型推断或显式声明确保类型安全。以下是用中文详细讲解 Rust 的数据类型,涵盖标量类型和复合类型,配以示例代码,简洁明了,适合初学者和需要快速复习的开发者。
1. 标量类型(Scalar Types)
标量类型表示单个值,Rust 提供四种主要标量类型:整数、浮点数、布尔值和字符。
1.1 整数类型(Integer Types)
Rust 支持有符号(i
)和无符号(u
)整数,长度包括 8、16、32、64、128 位,以及架构相关类型 isize
和 usize
。
类型 | 描述 | 范围示例(以 i32 和 u32 为例) |
---|---|---|
i8 | 8 位有符号整数 | -128 到 127 |
u8 | 8 位无符号整数 | 0 到 255 |
i16 | 16 位有符号整数 | -32,768 到 32,767 |
u16 | 16 位无符号整数 | 0 到 65,535 |
i32 | 32 位有符号整数 | -2,147,483,648 到 2,147,483,647 |
u32 | 32 位无符号整数 | 0 到 4,294,967,295 |
i64 | 64 位有符号整数 | ~ -2^63 到 2^63 – 1 |
u64 | 64 位无符号整数 | 0 到 2^64 – 1 |
i128 | 128 位有符号整数 | ~ -2^127 到 2^127 – 1 |
u128 | 128 位无符号整数 | 0 到 2^128 – 1 |
isize | 架构相关有符号 | 32 位系统:同 i32;64 位系统:同 i64 |
usize | 架构相关无符号 | 32 位系统:同 u32;64 位系统:同 u64 |
示例:
fn main() {
let x: i32 = -42; // 有符号整数
let y: u8 = 255; // 无符号整数
let z: usize = 100; // 架构相关,常用作索引
println!("x = {}, y = {}, z = {}", x, y, z);
}
说明:
- 默认整数类型为
i32
(类型推断时)。 - 整数溢出在调试模式会触发 panic,发布模式会回绕(wrap)。
1.2 浮点数类型(Floating-Point Types)
Rust 有两种浮点类型:f32
(单精度)和 f64
(双精度)。
类型 | 描述 | 示例值 |
---|---|---|
f32 | 32 位浮点数 | 3.14, -0.001, 2e-3 |
f64 | 64 位浮点数 | 3.14159265359, 1.0e10 |
示例:
fn main() {
let pi: f64 = 3.14159265359;
let small: f32 = 0.0001;
println!("pi = {}, small = {}", pi, small);
}
说明:
- 默认浮点类型为
f64
,因为精度更高且性能接近f32
。 - 支持科学计数法(如
2e-3
表示 0.002)。
1.3 布尔类型(Boolean Type)
Rust 的布尔类型为 bool
,只有两个值:true
和 false
。
示例:
fn main() {
let is_active: bool = true;
let is_zero: bool = false;
println!("is_active = {}, is_zero = {}", is_active, is_zero);
}
说明:
- 常用于条件判断(如
if
语句)。 - 布尔值占用 1 字节。
1.4 字符类型(Character Type)
Rust 的 char
类型表示 Unicode 标量值(4 字节),可以存储任意 Unicode 字符(如中文、表情符号等)。
示例:
fn main() {
let c: char = 'A';
let zh: char = '中';
let emoji: char = '😊';
println!("c = {}, zh = {}, emoji = {}", c, zh, emoji);
}
说明:
- 使用单引号
''
定义字符。 - 比 C/C++ 的
char
(1 字节)更灵活,支持多语言字符。
2. 复合类型(Compound Types)
复合类型将多个值组合成一个类型,Rust 提供元组(Tuple)和数组(Array)。
2.1 元组(Tuple)
元组是固定长度的集合,元素类型可以不同。
示例:
fn main() {
let tup: (i32, f64, char) = (42, 3.14, 'x');
// 解构
let (x, y, z) = tup;
println!("x = {}, y = {}, z = {}", x, y, z);
// 通过索引访问
println!("tup.0 = {}", tup.0);
}
说明:
- 元组用圆括号
()
定义。 - 可以通过解构或索引(如
tup.0
)访问元素。 - 最大长度为 12(受某些限制,如
Debug
trait)。
2.2 数组(Array)
数组是固定长度的集合,元素类型必须相同,存储在栈上。
示例:
fn main() {
let arr: [i32; 5] = [1, 2, 3, 4, 5]; // 指定类型和长度
let same: [i32; 3] = [0; 3]; // 初始化为 [0, 0, 0]
println!("arr = {:?}", arr); // 使用调试格式输出
println!("第一个元素: {}", arr[0]);
println!("same = {:?}", same);
}
说明:
- 数组类型写为
[T; N]
,T
是元素类型,N
是长度。 - 访问越界会引发编译期或运行时错误。
[x; N]
表示初始化 N 个值为 x 的数组。
注意:
- Rust 更常用动态数组
Vec<T>
(在标准库中),数组适合固定长度场景。
3. 字符串类型
Rust 有两种主要字符串类型:&str
(字符串切片)和 String
(可变字符串)。
3.1 &str
- 字符串切片,引用不可变的字符串数据。
- 通常作为字符串字面量(如
"hello"
)。
示例:
fn main() {
let s: &str = "Hello, Rust!";
println!("s = {}", s);
}
3.2 String
- 可变、堆分配的字符串,拥有所有权。
- 常用于动态字符串操作。
示例:
fn main() {
let mut s = String::from("Hello");
s.push_str(", Rust!"); // 添加字符串
println!("s = {}", s);
}
说明:
&str
轻量且不可变,适合静态字符串。String
可变,适合动态修改。- 两者可通过
&String
转换为&str
。
4. 其他类型
4.1 枚举(Enum)
枚举定义一组相关值,详见前文“Rust 基础语法”中的枚举部分。
示例:
enum Color {
Red,
Green,
Blue(u8), // 带数据的变体
}
fn main() {
let color = Color::Blue(255);
match color {
Color::Red => println!("红色"),
Color::Green => println!("绿色"),
Color::Blue(value) => println!("蓝色: {}", value),
}
}
4.2 结构体(Struct)
结构体定义自定义数据类型,详见前文“Rust 基础语法”。
示例:
struct Point {
x: i32,
y: i32,
}
fn main() {
let p = Point { x: 0, y: 0 };
println!("Point: ({}, {})", p.x, p.y);
}
4.3 切片(Slice)
切片是引用数据的一部分,常见于字符串和数组。
示例:
fn main() {
let arr = [1, 2, 3, 4, 5];
let slice: &[i32] = &arr[1..3]; // 切片包含 arr[1] 和 arr[2]
println!("slice = {:?}", slice); // 输出: [2, 3]
let s = String::from("hello");
let slice: &str = &s[0..2]; // 字符串切片
println!("slice = {}", slice); // 输出: he
}
说明:
- 切片是引用,不拥有数据。
- 范围语法
[start..end]
,end
不包含。
5. 类型转换
Rust 不支持隐式类型转换,必须显式转换。
5.1 使用 as
关键字
示例:
fn main() {
let x: i32 = 42;
let y: f64 = x as f64; // 转换为浮点数
println!("y = {}", y);
}
5.2 使用 into
和 from
某些类型可以通过 From
和 Into
trait 转换。
示例:
fn main() {
let s = String::from("hello"); // 从 &str 到 String
let num: i32 = "42".parse().unwrap(); // 字符串解析为整数
println!("s = {}, num = {}", s, num);
}
说明:
parse
返回Result
,需用unwrap
或妥善处理错误。String::from
是常见的构造方法。
6. 注意事项
- 类型推断:
- Rust 编译器会根据上下文推断类型,但复杂情况需显式指定。
- 内存安全:
- 数组和字符串操作受所有权和借用规则约束,防止越界或非法访问。
- 性能:
- 标量类型和数组存储在栈上,性能高。
String
和Vec
存储在堆上,适合动态数据。
- Unicode 支持:
char
和&str
支持 Unicode,处理中文等字符时需注意字节与字符的区别。
- 调试输出:
- 使用
{:?}
格式化需要类型实现Debug
trait,结构体和枚举需添加#[derive(Debug)]
。
7. 总结
Rust 的数据类型分为:
- 标量类型:整数(
i32
,u32
等)、浮点数(f32
,f64
)、布尔(bool
)、字符(char
)。 - 复合类型:元组(
()
)、数组([T; N]
)。 - 字符串:
&str
(不可变切片)、String
(可变堆分配)。 - 其他:枚举(
enum
)、结构体(struct
)、切片(&[T]
,&str
)。
通过这些类型,Rust 提供了灵活且安全的编程模型。如果需要更深入的讲解(如自定义类型、trait 关联类型或高级转换),请告诉我!