类型转换(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的转换将产生最接近的可能值(舍入到最近,连接到偶数)