类型转换(Casts)

类型转换(Casts)是强制转换(coercion)的超集:每个强制转换都可以通过cast显式地调用.但是有些转换(conversions)需要cast.虽然强制转换是普遍存在的并且在很大程度上是无害的,但这些”真正的类型转换(true casts)”是罕见的,并且具有潜在的危险性.因此,类型转换(cast)必须使用as关键字显式调用:expr as Type.

真正的类型转换通常围绕原始指针和基本数字类型.即使它们很危险,这些类型转换在运行时也是绝对可靠的.如果一个类型转换触发一些微妙的角落情况,则不会发出这种情况的指示.类型转换将会成功.也就是说,类型转换必须在类型级别有效,否则它们将被静态防止.例如,7u8 as bool将无法编译.

这就是说,类型转换不是unsafe,因为他们通常不会 自己(on their own) 违反内存安全.例如,将整数转换为原始指针很容易导致可怕的事情.但是,创建指针本身的行为是安全的,因为实际使用原始指针已被标记为unsafe.

这是所有真正的类型转换的详尽列表.为简洁起见,我们将使用*来表示*const* mut,并使用integer来表示任何整数原语:

  • *T as *U 其中 T, U: Sized

  • *T as *U TODO:解释无大小的(unsized)情况

  • *T as integer

  • integer as *T

  • number as number

  • field-less enum as integer

  • bool as integer

  • char as integer

  • u8 as char

  • &[T; n] as *const T

  • fn as *T 其中 T: Sized

  • fn as integer

请注意,在转换原始切片—*const [u16] as *const [u8]时不会调整长度,创建的切片仅包含原始内存的一半.

类型转换不是传递性的,即,即使e as U1 as U2是有效的表达式,e as U2不一定如此.

对于数字类型转换,有很多情况需要考虑:

  • 在相同大小的两个整数(例如,i32 -> u32)之间进行转换是一种无操作(no-op)

  • 从较大的整数转换为较小的整数(例如,u32 -> u8)将截断

  • 从较小的整数转换为较大的整数(例如,u8 -> u32)会

    • 如果源是无符号的,则为零扩展(zero-extend)

    • 如果源有符号的,则为符号扩展(sign-extend)

  • 从浮点数转换为整数将使浮点数向零舍入,当浮点数超出整数范围时,会产生”饱和转换(saturating cast)”

    • 太大的浮点数会变成可能的最大整数

    • 太小的浮点数产生可能的最小整数

    • NaN产生零

  • 从整数转换为浮点数将生成整数的浮点表示,必要时舍入(舍入到最近,连接到偶数)

  • 从f32到f64的转换是完美无损的

  • 从f64到f32的转换将产生最接近的可能值(舍入到最近,连接到偶数)