类型转换
Rust 是类型安全的语言,不提供原生类型之间的隐式类型转换,但可以使用 as
关键字进行显式类型转换。
as
转换
Rust 不允许两种不同的类型进行比较、计算。下面列出常用的转换形式:
rust
// 不显示类型转换产生的溢出警告。
#![allow(overflowing_literals)]
fn main() {
let decimal = 65.4321_f32;
// 错误!不提供隐式转换
let integer: u8 = decimal;
// 改正 ^ 注释掉这一行
// 可以显式转换
let integer = decimal as u8;
let character = integer as char;
println!("Casting: {} -> {} -> {}", decimal, integer, character);
// 当把任何类型转换为无符号类型 T 时,会不断加上或减去 (std::T::MAX + 1)
// 直到值位于新类型 T 的范围内。
// 1000 已经在 u16 的范围内
println!("1000 as a u16 is: {}", 1000 as u16);
// 1000 - 256 - 256 - 256 = 232
// 事实上的处理方式是:从最低有效位(LSB,least significant bits)开始保留
// 8 位,然后剩余位置,直到最高有效位(MSB,most significant bit)都被抛弃。
// 译注:MSB 就是二进制的最高位,LSB 就是二进制的最低位,按日常书写习惯就是
// 最左边一位和最右边一位。
println!("1000 as a u8 is : {}", 1000 as u8);
// -1 + 256 = 255
println!(" -1 as a u8 is : {}", (-1i8) as u8);
// 对正数,这就和取模一样。
println!("1000 mod 256 is : {}", 1000 % 256);
// 当然如果数值已经在目标类型的范围内,就直接把它放进去。
println!(" 128 as a i16 is: {}", 128 as i16);
// 当转换到有符号类型时,(位操作的)结果就和 “先转换到对应的无符号类型,
// 如果 MSB 是 1,则该值为负” 是一样的。
println!(" 128 as a i8 is : {}", 128 as i8);
// 重复之前的例子
// 1000 as u8 -> 232
println!("1000 as a u8 is : {}", 1000 as u8);
// 232 的二进制补码是 -24
println!(" 232 as a i8 is : {}", 232 as i8);
}
注意,因为每个类型能表达的数据范围不同,如果把范围较大的类型转换成较小的类型,会造成错误,因此我们需要把范围较小的类型转换成较大的类型,来避免这些问题的发生;此外在,类型转换的同时,要注意表示精度的损失。