Rust 数据类型
概述
Rust 是静态类型语言,编译时必须知道所有变量的类型。本章将深入学习 Rust 的类型系统,包括标量类型、复合类型、以及类型转换等内容。
🔢 标量类型
整数类型
rust
fn integer_types() {
// 有符号整数
let i8_max: i8 = 127;
let i8_min: i8 = -128;
let i16_val: i16 = 32_767;
let i32_val: i32 = 2_147_483_647;
let i64_val: i64 = 9_223_372_036_854_775_807;
let i128_val: i128 = 170_141_183_460_469_231_731_687_303_715_884_105_727;
let isize_val: isize = 1000; // 平台相关大小
println!("有符号整数: {}, {}, {}, {}, {}, {}, {}",
i8_max, i8_min, i16_val, i32_val, i64_val, i128_val, isize_val);
// 无符号整数
let u8_max: u8 = 255;
let u16_max: u16 = 65_535;
let u32_max: u32 = 4_294_967_295;
let u64_max: u64 = 18_446_744_073_709_551_615;
let u128_max: u128 = 340_282_366_920_938_463_463_374_607_431_768_211_455;
let usize_val: usize = 1000; // 平台相关大小
println!("无符号整数: {}, {}, {}, {}, {}, {}",
u8_max, u16_max, u32_max, u64_max, u128_max, usize_val);
// 整数字面量的不同表示法
let decimal = 98_222; // 十进制
let hex = 0xff; // 十六进制
let octal = 0o77; // 八进制
let binary = 0b1111_0000; // 二进制
let byte = b'A'; // 字节字面量(u8)
println!("不同进制: {} {} {} {} {}", decimal, hex, octal, binary, byte);
// 类型后缀
let typed_int = 42u32;
let another = 100_i64;
println!("类型后缀: {}, {}", typed_int, another);
}浮点类型
rust
fn floating_point_types() {
// 单精度浮点
let f32_val: f32 = 3.14159;
let f32_scientific: f32 = 1.23e-4;
// 双精度浮点(默认)
let f64_val: f64 = 2.718281828459045;
let default_float = 3.14; // 默认是 f64
println!("浮点数: {} {} {} {}", f32_val, f32_scientific, f64_val, default_float);
// 浮点数的特殊值
let infinity = f64::INFINITY;
let neg_infinity = f64::NEG_INFINITY;
let nan = f64::NAN;
println!("特殊值: {} {} {}", infinity, neg_infinity, nan);
// 浮点数运算
let sum = 5.0 + 10.0;
let difference = 95.5 - 4.3;
let product = 4.0 * 30.0;
let quotient = 56.7 / 32.2;
let remainder = 43.0 % 5.0;
println!("运算: {} {} {} {} {}", sum, difference, product, quotient, remainder);
// 浮点数比较的注意事项
let a = 0.1 + 0.2;
let b = 0.3;
println!("0.1 + 0.2 = {}", a);
println!("0.3 = {}", b);
println!("相等吗? {}", a == b); // 可能是 false
// 正确的浮点数比较
let epsilon = f64::EPSILON;
println!("近似相等吗? {}", (a - b).abs() < epsilon);
}布尔类型
rust
fn boolean_type() {
let t = true;
let f: bool = false; // 显式类型注解
println!("布尔值: {}, {}", t, f);
// 布尔运算
let and_result = t && f; // 逻辑与
let or_result = t || f; // 逻辑或
let not_result = !t; // 逻辑非
println!("逻辑运算: {} {} {}", and_result, or_result, not_result);
// 短路求值
let result1 = false && expensive_operation(); // expensive_operation 不会被调用
let result2 = true || expensive_operation(); // expensive_operation 不会被调用
println!("短路求值: {} {}", result1, result2);
// 布尔到数字的转换
let bool_as_int = t as i32;
println!("布尔转数字: {}", bool_as_int);
}
fn expensive_operation() -> bool {
println!("执行昂贵操作");
true
}字符类型
rust
fn character_type() {
let c = 'z';
let z = 'ℤ';
let heart_eyed_cat = '😻';
let chinese = '中';
println!("字符: {} {} {} {}", c, z, heart_eyed_cat, chinese);
// 字符字面量的不同表示
let newline = '\n';
let tab = '\t';
let backslash = '\\';
let quote = '\'';
println!("转义字符: [{}] [{}] [{}] [{}]", newline, tab, backslash, quote);
// ASCII 字符
let ascii_a = '\x41'; // 'A'
println!("ASCII: {}", ascii_a);
// Unicode 字符
let unicode_heart = '\u{2764}'; // ❤
let unicode_emoji = '\u{1F600}'; // 😀
println!("Unicode: {} {}", unicode_heart, unicode_emoji);
// 字符相关方法
println!("是否为字母: {}", 'a'.is_alphabetic());
println!("是否为数字: {}", '5'.is_numeric());
println!("是否为小写: {}", 'a'.is_lowercase());
println!("转大写: {}", 'a'.to_uppercase().next().unwrap());
}📦 复合类型
元组类型
rust
fn tuple_type() {
// 基本元组
let tup: (i32, f64, u8) = (500, 6.4, 1);
// 解构元组
let (x, y, z) = tup;
println!("解构元组: {}, {}, {}", x, y, z);
// 通过索引访问
let first = tup.0;
let second = tup.1;
let third = tup.2;
println!("索引访问: {}, {}, {}", first, second, third);
// 嵌套元组
let nested: ((i32, i32), (i32, i32)) = ((1, 2), (3, 4));
println!("嵌套元组: {:?}", nested);
// 单元素元组
let single_element = (42,); // 注意逗号
let not_tuple = (42); // 这不是元组,只是括号
println!("单元素元组: {:?}", single_element);
// 空元组(单元类型)
let unit = ();
println!("单元类型: {:?}", unit);
// 元组作为函数返回值
let (sum, product) = calculate(4, 5);
println!("计算结果: 和={}, 积={}", sum, product);
}
fn calculate(a: i32, b: i32) -> (i32, i32) {
(a + b, a * b)
}数组类型
rust
fn array_type() {
// 基本数组
let arr = [1, 2, 3, 4, 5];
println!("数组: {:?}", arr);
// 显式类型和长度
let arr: [i32; 5] = [1, 2, 3, 4, 5];
println!("类型注解数组: {:?}", arr);
// 相同值初始化
let zeros = [0; 5]; // [0, 0, 0, 0, 0]
let threes = [3; 4]; // [3, 3, 3, 3]
println!("初始化数组: {:?}, {:?}", zeros, threes);
// 访问数组元素
let first = arr[0];
let second = arr[1];
println!("数组元素: {}, {}", first, second);
// 数组长度
println!("数组长度: {}", arr.len());
// 数组切片
let slice = &arr[1..4]; // 不包含索引4
println!("切片: {:?}", slice);
// 遍历数组
for element in arr.iter() {
println!("元素: {}", element);
}
// 带索引遍历
for (index, element) in arr.iter().enumerate() {
println!("索引 {}: {}", index, element);
}
// 多维数组
let matrix: [[i32; 3]; 2] = [[1, 2, 3], [4, 5, 6]];
println!("矩阵: {:?}", matrix);
println!("矩阵元素: {}", matrix[1][2]); // 6
}🔄 类型转换
显式类型转换
rust
fn explicit_conversion() {
// 数值类型转换
let integer = 42i32;
let float = integer as f64;
let byte = integer as u8;
println!("转换: {} -> {} -> {}", integer, float, byte);
// 可能丢失精度的转换
let large_number = 1000i32;
let truncated = large_number as u8; // 可能截断
println!("截断: {} -> {}", large_number, truncated);
// 浮点到整数的转换
let pi = 3.14f64;
let truncated_pi = pi as i32; // 截断小数部分
println!("浮点转整数: {} -> {}", pi, truncated_pi);
// 字符到数字的转换
let digit_char = '5';
let digit_value = digit_char as u8; // ASCII 值
println!("字符 '{}' 的 ASCII 值: {}", digit_char, digit_value);
// 布尔到数字的转换
let true_as_int = true as i32;
let false_as_int = false as i32;
println!("布尔转数字: {} -> {}, {} -> {}", true, true_as_int, false, false_as_int);
}安全类型转换
rust
fn safe_conversion() {
use std::convert::TryInto;
// TryInto trait 提供安全转换
let large_number: i64 = 1000;
match large_number.try_into() {
Ok(small_number) => {
let small: i32 = small_number;
println!("安全转换成功: {} -> {}", large_number, small);
}
Err(e) => println!("转换失败: {}", e),
}
// 转换可能失败的情况
let too_large: i64 = i64::MAX;
match too_large.try_into() {
Ok(small_number) => {
let small: i32 = small_number;
println!("转换成功: {}", small);
}
Err(e) => println!("转换失败: {}", e),
}
// 字符串到数字的解析
let number_string = "42";
match number_string.parse::<i32>() {
Ok(number) => println!("解析成功: {} -> {}", number_string, number),
Err(e) => println!("解析失败: {}", e),
}
let invalid_string = "not_a_number";
match invalid_string.parse::<i32>() {
Ok(number) => println!("解析成功: {}", number),
Err(e) => println!("解析失败: {}", e),
}
}🏷️ 类型别名
定义类型别名
rust
// 类型别名
type Kilometers = i32;
type Thunk = Box<dyn Fn() + Send + 'static>;
fn type_aliases() {
// 使用类型别名
let distance: Kilometers = 100;
println!("距离: {} 公里", distance);
// 类型别名提高可读性
type UserId = u32;
type UserName = String;
type UserAge = u8;
let id: UserId = 12345;
let name: UserName = String::from("Alice");
let age: UserAge = 30;
println!("用户: ID={}, 姓名={}, 年龄={}", id, name, age);
// 复杂类型的别名
type Matrix = Vec<Vec<i32>>;
type Point3D = (f64, f64, f64);
type Result<T> = std::result::Result<T, Box<dyn std::error::Error>>;
let matrix: Matrix = vec![vec![1, 2], vec![3, 4]];
let point: Point3D = (1.0, 2.0, 3.0);
println!("矩阵: {:?}", matrix);
println!("3D点: {:?}", point);
}🔍 类型推断
编译器类型推断
rust
fn type_inference() {
// 编译器可以推断类型
let x = 42; // i32
let y = 3.14; // f64
let z = true; // bool
let s = "hello"; // &str
println!("推断类型: {}, {}, {}, {}", x, y, z, s);
// 根据使用情况推断
let mut vec = Vec::new();
vec.push(1); // 现在编译器知道这是 Vec<i32>
println!("向量: {:?}", vec);
// 需要类型注解的情况
let parsed: i32 = "42".parse().expect("不是数字");
println!("解析结果: {}", parsed);
// 或者使用 turbofish 语法
let parsed2 = "42".parse::<i32>().expect("不是数字");
println!("Turbofish 解析: {}", parsed2);
// 集合的类型推断
let numbers = vec![1, 2, 3, 4, 5]; // Vec<i32>
let words = vec!["hello", "world"]; // Vec<&str>
println!("数字集合: {:?}", numbers);
println!("单词集合: {:?}", words);
}📏 类型大小和对齐
查看类型大小
rust
fn type_sizes() {
use std::mem;
// 标量类型大小
println!("类型大小(字节):");
println!("bool: {}", mem::size_of::<bool>());
println!("char: {}", mem::size_of::<char>());
println!("i8: {}", mem::size_of::<i8>());
println!("i16: {}", mem::size_of::<i16>());
println!("i32: {}", mem::size_of::<i32>());
println!("i64: {}", mem::size_of::<i64>());
println!("i128: {}", mem::size_of::<i128>());
println!("isize: {}", mem::size_of::<isize>());
println!("f32: {}", mem::size_of::<f32>());
println!("f64: {}", mem::size_of::<f64>());
// 复合类型大小
println!("(i32, i32): {}", mem::size_of::<(i32, i32)>());
println!("[i32; 5]: {}", mem::size_of::<[i32; 5]>());
println!("&str: {}", mem::size_of::<&str>());
println!("String: {}", mem::size_of::<String>());
println!("Vec<i32>: {}", mem::size_of::<Vec<i32>>());
// 对齐信息
println!("\n类型对齐:");
println!("i32 对齐: {}", mem::align_of::<i32>());
println!("i64 对齐: {}", mem::align_of::<i64>());
println!("(i8, i64) 对齐: {}", mem::align_of::<(i8, i64)>());
}📝 本章小结
通过本章学习,你应该掌握了:
标量类型
- ✅ 整数类型的范围和使用
- ✅ 浮点类型的精度和特殊值
- ✅ 布尔类型和字符类型
- ✅ 字面量的不同表示法
复合类型
- ✅ 元组的定义和使用
- ✅ 数组的操作和遍历
- ✅ 多维数组和切片
- ✅ 类型推断机制
类型转换
- ✅ 显式类型转换(as)
- ✅ 安全类型转换(TryInto)
- ✅ 字符串解析和错误处理
- ✅ 类型别名的定义和使用
最佳实践
- 选择合适的数值类型
- 注意浮点数比较
- 使用安全的类型转换
- 利用类型推断简化代码
继续学习:下一章 - Rust 注释