Rust 提供多种机制用来变更、定义基础类型与自定义类型。
- 基础类型之间强制转换(类型投射 Casting)
- 为字面量指定目标类型
- 类型推断
- 类型别名
我们先学习,强制类型转换
强制类型转换 Casting
Rust 不存在基础类型之间的隐式自动类型转换(隐式强制 coercion)。 想要转换类型,必须使用 as 关键字显式强制转换。
Rust 所有整数互相转换行为都是明确定义、可预测的。
先看例子
// 允许字面量溢出,屏蔽溢出相关编译警告
#![allow(overflowing_literals)]
fn main() {
let decimal = 65.4321_f32;
// 编译报错!禁止隐式类型转换
// let integer: u8 = decimal; //无隐式转换:f32 不能直接赋值给 u8,必须写 as
// 请注释掉此行代码 观察
// 使用 as 显式强制转换
let integer = decimal as u8;
let character = integer as char;
// 编译报错:转换存在限制,浮点数不能直接转为 char
// let character = decimal as char;
// 请注释掉此行
println!("Casting: {} -> {} -> {}", decimal, integer, character);
// ===== 整数溢出转换规则 =====
// 将任意数值强制转换为无符号类型 T 时:
// 在开启 #![allow(overflowing_literals)] 的前提下
// 不断 ± (T::MAX + 1),直到数值落入类型取值范围;
// 如果不开启该特性,溢出字面量直接编译报错。
// 1000 在 u16 取值范围内,直接保留原值
println!("1000 as a u16 is: {}", 1000 as u16);
// 1000 - 256 - 256 - 256 = 232
// 底层原理:仅保留最低8个比特位(最低有效位 LSB),高位直接截断丢弃
println!("1000 as a u8 is : {}", 1000 as u8);
// -1 + 256 = 255
println!(" -1 as a u8 is : {}", (-1i8) as u8);
// 正数场景下,等价于对类型最大值+1取模运算
println!("1000 mod 256 is : {}", 1000 % 256);
// ===== 转为有符号整数规则 =====
// 转换到有符号类型时:
// 先转为同等宽度无符号类型,再解读二进制补码。
// 如果二进制最高位是1,则代表负数(补码规则)。
// 128 在 i16 范围内,原值保留
println!(" 128 as a i16 is: {}", 128 as i16);
// 边界案例:8位二进制下 128 的补码表示就是 -128
println!(" 128 as a i8 is : {}", 128 as i8);
// 承接上例:1000 → u8 截断后 =232
println!("1000 as a u8 is : {}", 1000 as u8);
// 二进制 232 视作i8有符号数,补码解析结果为 -24
println!(" 232 as a i8 is : {}", 232 as i8);
// ===== Rust 1.45 起:浮点数 → 整数的 as 转换是【饱和截断】saturating cast =====
// 浮点数超出整数上限 → 等于整数最大值
// 浮点数低于整数下限 → 等于整数最小值
println!(" 300.0 as u8 is : {}", 300.0_f32 as u8); // 超过255 → 255
println!("-100.0 as u8 is : {}", -100.0_f32 as u8); // 小于0 → 0
println!(" nan as u8 is : {}", f32::NAN as u8); // NaN → 0
// 不安全方案:to_int_unchecked
// 避开饱和转换,直接底层比特截断;存在运行时开销,但可以绕过饱和逻辑
// 风险:结果会溢出,产生不符合预期的值,必须谨慎使用!
unsafe {
println!(" 300.0 as u8 is : {}", 300.0_f32.to_int_unchecked::<u8>());
println!("-100.0 as u8 is : {}", (-100.0_f32).to_int_unchecked::<u8>());
println!(" nan as u8 is : {}", f32::NAN.to_int_unchecked::<u8>());
}
}Code language: Rust (rust)
输出结果
Casting: 65.4321 -> 65 -> A
1000 as a u16 is: 1000
1000 as a u8 is : 232
-1 as a u8 is : 255
1000 mod 256 is : 232
128 as a i16 is: 128
128 as a i8 is : -128
1000 as a u8 is : 232
232 as a i8 is : -24
300.0 as u8 is : 255
-100.0 as u8 is : 0
nan as u8 is : 0
300.0 as u8 is : 44
-100.0 as u8 is : 156
nan as u8 is : 0Code language: JavaScript (javascript)
1 Rust 没有基础类型隐式转换
不会自动帮你把 f32→u8、i32→u16。
浮点、整数互相赋值直接编译报错。
let decimal = 65.4321_f32;
let integer: u8 = decimal; // 报错,禁止隐式转换Code language: JavaScript (javascript)
2:as 显式类型转换基础用法
用法
值 as 目标类型Code language: JavaScript (javascript)
let decimal = 65.4321_f32;
let integer = decimal as u8; // float → u8
let character = integer as char; // u8 → charCode language: JavaScript (javascript)
3 :转换限制:浮点数不能直接 as char
decimal as char 错误 只能先转为整数,再转 char。
4 浮点数 → 整数:饱和转换 saturating cast
使用 as 将浮点转整数规则:
- 浮点 > 目标整数最大值 → 返回最大值
- 浮点 < 目标整数最小值 → 返回最小值
- NaN → 0
300.0_f32 as u8; // 300>255 → 255
-100.0_f32 as u8; // -100<0 → 0
f32::NAN as u8; // NaN → 0Code language: PHP (php)
5 整数转无符号整数底层逻辑(截断 / 模运算)
开启 #![allow(overflowing_literals)],否则溢出字面量编译报错。
- 数值超出范围时,等价于 保留最低有效比特位(高位截断)
- 数学表达:对
2^比特数取模 示例:
1000 as u8→ 1000 % 256 = 232-1i8 as u8→ 255
Previous: 变量绑定(Variable Bindings)
Next: 字面量(Literals)