类型转换

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 将浮点转整数规则:

  1. 浮点 > 目标整数最大值 → 返回最大值
  2. 浮点 < 目标整数最小值 → 返回最小值
  3. 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)],否则溢出字面量编译报错。

  1. 数值超出范围时,等价于 保留最低有效比特位(高位截断)
  2. 数学表达:对 2^比特数 取模 示例:
  • 1000 as u8 → 1000 % 256 = 232
  • -1i8 as u8 → 255

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注