編集者注:この質問は、Rust 1.0より前のバージョンからのものであり、Rust 1.0。 。
(たとえば)usize
からu32
に変換する慣用的な方法は何ですか?
たとえば、4294967295us as u32
を使用したキャストは機能し、 Rust 0.12型キャストに関するリファレンスドキュメントは と言います
数値は任意の数値型にキャストできます。生のポインタ値は、整数型または生のポインタ型との間でキャストできます。その他のキャストはサポートされていないため、コンパイルに失敗します。
しかし4294967296us as u32
は静かにオーバーフローし、結果0を返します。
私は、 ToPrimitive
と FromPrimitive
を見つけました。これらは、to_u32() -> Option<u32>
などの素敵な関数を提供します。しかし、それらは不安定とマークされています:
#[unstable(feature = "core", reason = "trait is likely to be removed")]
数値(およびポインター)型間で変換する慣用的な(そして安全な)方法は何ですか?
プラットフォームに依存するisize
/usize
のサイズは、この質問をする理由の1つです。元のシナリオは、ツリーを表現できるようにu32
からusize
に変換したかったからです。 Vec<u32>
(たとえばlet t = Vec![0u32, 0u32, 1u32]
の場合、ノード2の祖父母を取得するにはt[t[2us] as usize]
になります)で、usize
が32ビット未満の場合、どのように失敗するのでしょうか。
ToPrimitive
/FromPrimitive
で理想的には[...]
ToPrimitive
[...]はすべて削除され、Cに似た列挙型を扱うより原則的な方法が採用されます。
それまでの間、これらの特性は num crate で生き続けます。
ここに問題はありません。 From
を使用して、損失が発生していないことを明示します。
fn example(v: i8) -> i32 {
i32::from(v) // or v.into()
}
as
を使用することもできますが、不要な場合は使用しないことをお勧めします(以下を参照)。
fn example(v: i8) -> i32 {
v as i32
}
一般的に意味のある単一の方法はありません-1つのスペースに2つのものを収める方法を尋ねています。最初の良い試みの1つは、値が適合する場合はOption
— Some
を使用し、そうでない場合はNone
を使用することです。その後、必要に応じて、プログラムを失敗させるか、デフォルト値に置き換えることができます。
Rust 1.34なので、 TryFrom
を使用できます。
use std::convert::TryFrom;
fn example(v: i32) -> Option<i8> {
i8::try_from(v).ok()
}
その前に、同様のコードを自分で記述する必要があります。
fn example(v: i32) -> Option<i8> {
if v > std::i8::MAX as i32 {
None
} else {
Some(v as i8)
}
}
as
が行うことしかし、
4294967296us as u32
は静かにオーバーフローし、結果0を返します
小さい型に変換する場合、as
は、符号を含む上位ビットを無視して、数値の下位ビットのみを取得します。
fn main() {
let a: u16 = 0x1234;
let b: u8 = a as u8;
println!("0x{:04x}, 0x{:02x}", a, b); // 0x1234, 0x34
let a: i16 = -257;
let b: u8 = a as u8;
println!("0x{:02x}, 0x{:02x}", a, b); // 0xfeff, 0xff
}