类型转换 - Rust By Example
Description: Rust by Example (RBE) is a collection of runnable examples that illustrate various Rust concepts and standard libraries.

## Keyboard shortcuts

Press `←` or `→` to navigate between chapters

Press `S` or `/` to search in the book

Press `?` to show this help

Press `Esc` to hide this help

# 类型转换

Rust 不支持原始类型之间的隐式类型转换（强制转换）。但可以使用 `as` 关键字进行显式类型转换（转型）。

整数类型之间的转换规则通常遵循 C 语言惯例，但 C 中存在未定义行为的情况除外。在 Rust 中，所有整数类型之间的转换行为都有明确定义。

    // Suppress all errors from casts which overflow.
    #![allow(overflowing_literals)]

    fn main() {
        let decimal = 65.4321_f32;

        // 错误！不允许隐式转换
        let integer: u8 = decimal;
        // 修复：^ 注释掉此行

        // 显式转换
        let integer = decimal as u8;
        let character = integer as char;

        // 错误！转换规则有限制。
        // 浮点数不能直接转换为字符。
        let character = decimal as char;
        // 修复：^ 注释掉此行

        println!("类型转换：{} -> {} -> {}", decimal, integer, character);

        // when casting any value to an unsigned type, T,
        // T::MAX + 1 is added or subtracted until the value
        // fits into the new type ONLY when the #![allow(overflowing_literals)]
        // lint is specified like above. Otherwise there will be a compiler error.

        // 1000 已经适合 u16
        println!("1000 转换为 u16 是：{}", 1000 as u16);

        // 1000 - 256 - 256 - 256 = 232
        // 实际上，保留了最低有效位（LSB）的前 8 位，
        // 而朝最高有效位（MSB）方向的其余位被截断。
        println!("1000 转换为 u8 是：{}", 1000 as u8);
        // -1 + 256 = 255
        println!("  -1 转换为 u8 是：{}", (-1i8) as u8);

        // 对于正数，这等同于取模运算
        println!("1000 对 256 取模是：{}", 1000 % 256);

        // 当转换为有符号类型时，（按位）结果等同于
        // 先转换为对应的无符号类型。如果该值的最高有效位
        // 为 1，则该值为负数。

        // 当然，如果已经适合的话就不需要转换。
        println!(" 128 转换为 i16 是：{}", 128 as i16);

        // 边界情况：128 在 8 位二进制补码表示中为 -128
        println!(" 128 转换为 i8 是：{}", 128 as i8);

        // 重复上面的例子
        // 1000 转换为 u8 -> 232
        println!("1000 转换为 u8 是：{}", 1000 as u8);
        // 而 232 在 8 位二进制补码表示中为 -24
        println!(" 232 转换为 i8 是：{}", 232 as i8);

        // 从 Rust 1.45 开始，`as` 关键字在浮点数转整数时执行*饱和转换*
        // 如果浮点值超出上界或低于下界，返回值
        // 将等于所越过的边界值。

        // 300.0 转换为 u8 是 255
        println!(" 300.0 转换为 u8 是：{}", 300.0_f32 as u8);
        // -100.0 转换为 u8 是 0
        println!("-100.0 转换为 u8 是：{}", -100.0_f32 as u8);
        // NaN 转换为 u8 是 0
        println!("   NaN 转换为 u8 是：{}", f32::NAN as u8);

        // 这种行为会产生少量运行时开销，可以通过不安全方法避免，
        // 但结果可能溢出并返回**不可靠的值**。请谨慎使用这些方法：
        unsafe {
            // 300.0 转换为 u8 是 44
            println!(" 300.0 转换为 u8 是：{}", 300.0_f32.to_int_unchecked::<u8>());
            // -100.0 转换为 u8 是 156
            println!("-100.0 转换为 u8 是：{}", (-100.0_f32).to_int_unchecked::<u8>());
            // NaN 转换为 u8 是 0
            println!("   NaN 转换为 u8 是：{}", f32::NAN.to_int_unchecked::<u8>());
        }
    }