キャスト
キャストは型強制のスーパーセットです。すなわち、全ての型強制は、キャストを通じて
明示的に引き起こすことが出来ます。しかし、いくつかの変換はキャストを必要とします。
型強制は普及していて、大体の場合、害はないのですが、これらの "真のキャスト" は稀で、
潜在的に危険です。ですから、キャストは as
キーワードを用いて、明示的に
実行しなければなりません: expr as Type
真のキャストは一般的に、生ポインタやプリミティブ型の数値型に関係します。
真のキャストは危険ですが、これらのキャストは実行時に失敗しません。
もしキャストが何か微妙なコーナーケースを引き起こしたとしても、
何の指摘もされないでしょう。キャストは単に成功します。そうは言ったものの、
キャストは型レベルで正しくなければなりません。でなければそのキャストは静的に
防がれます。例えば、 7u8 as bool
はコンパイルできません。
そうは言っていますが、キャストは unsafe
ではありません。なぜなら、
キャストは一般的に、それ自体でメモリ安全性を侵害しないからです。
例えば、整数を生ポインタに変換すると、非常に簡単にひどい問題を引き起しうるでしょう。
しかしながら、ポインタを生成する事自体は安全です。なぜなら、実際に生ポインタを使用すること
が既に unsafe
としてマークされているからです。
これは、全ての真のキャストを網羅しているリストです。簡潔にするため、 *
を *const
か *mut
の
どちらかとして使い、 integer
を整数型プリミティブの何かとして用います。
*T as *U
但しT, U: Sized
*T as *U
TODO: サイズが不定の場合について説明する*T as integer
integer as *T
number as number
C-like-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
は
必ずしも有効とは限りません。
数値のキャストに関しては、かなり多くの事項について考える必要があります。
- 同じ大きさの 2 つの整数の間でのキャスト (例: i32 -> u32) は no-op です
- 大きい方の整数から小さい方の整数へのキャスト (例: u32 -> u8) は切り捨てが発生します
- 小さい方の整数から大きい方の整数へのキャスト (例: u8 -> u32) は
- もし小さい方の整数が符号なしの場合、ゼロ拡張されます
- もし小さい方の整数が符号ありの場合、符号拡張されます
- 浮動小数点数から整数へのキャストは、小数点以下が切り捨てられます
- 注意: 現在もし丸められた値が、キャスト先の整数型で表現できない場合、未定義動作を引き起こします。 これはバグで、将来修正されます。
- 整数から浮動小数点数へのキャストは、整数を浮動小数点数で表現します。必要ならば丸められます (丸めの方針は指定されていません)
- f32 から f64 へのキャストは完全で、損失はありません
- f64 から f32 へのキャストは、最も近い表現可能な値となります (丸めの方針は指定されていません)
- 注意: 現在もし値が f32 で表現可能な最大の値より大きい、あるいは最小の値より小さい有限の値である場合、未定義動作を引き起こします。 これはバグで、将来修正されます。