web-dev-qa-db-ja.com

u32とusizeの間で慣用的に変換する方法は?

このコードは機能し、「b」を出力します。

_fn main() {
    let s = "abc";
    let ch = s.chars().nth(1).unwrap();
    println!("{}", ch);
}
_

一方、このコードは不一致タイプのエラーになります。

_fn main() {
    let s = "abc";
    let n: u32 = 1;
    let ch = s.chars().nth(n).unwrap();
    println!("{}", ch);
}
_
_error[E0308]: mismatched types
 --> src/main.rs:5:28
  |
5 |     let ch = s.chars().nth(n).unwrap();
  |                            ^ expected usize, found u32
_

何らかの外部的な理由により、変数nに_u32_タイプを使用する必要があります。 _u32_をusizeに変換してnth()で使用するにはどうすればよいですか?

20
Sajuuk

as演算子は、すべての数値タイプで機能します。

let ch = s.chars().nth(n as usize).unwrap();

Rustは整数をキャストするように強制し、符号またはオーバーフローを確実に認識します。

整数定数には、型の接尾辞を付けることができます。

let n = 1u32;

ただし、-1i32などの負の定数は内部では-1i32であることに注意してください。

明示的な型指定なしで宣言された整数変数は{integer}として示され、メソッド呼び出しの1つから適切に推測されます。

19
Tatsuyuki Ishi

あなたができる最も慎重なことは TryFrom を使用し、値がusizeに収まらない場合にパニックすることです:

use std::convert::TryFrom;

fn main() {
    let s = "abc";
    let n: u32 = 1;
    let n_us = usize::try_from(n).unwrap();
    let ch = s.chars().nth(n_us).unwrap();
    println!("{}", ch);
}

盲目的にasを使用すると、usizeが32ビットより小さいプラットフォームで実行すると、コードが不可解な方法で失敗します。たとえば、一部のマイクロコントローラーは、ネイティブサイズとして16ビット整数を使用します。

fn main() {
    let n: u32 = 0x1_FF_FF;
    // Pretend that `usize` is 16-bit
    let n_us: u16 = n as u16;

    println!("{}, {}", n, n_us); // 131071, 65535
}
10
Shepmaster

コードをコンパイルしようとすると、かなり異なる答えが得られます。数値_1_を型_i32_の変数に置き換えます。

_error[E0308]: mismatched types
 --> src/main.rs:5:28
  |
5 |     let ch = s.chars().nth(n).unwrap();
  |                            ^ expected usize, found i32
help: you can convert an `i32` to `usize` and panic if the converted value wouldn't fit
  |
5 |     let ch = s.chars().nth(n.try_into().unwrap()).unwrap();
  |    
_

つまり、コンパイラーは、TryIntoに依存して返される特性 TryFrom を利用するn.try_into().unwrap()を使用することをお勧めします_Result<T, T::Error>_。そのため、.unwrap()を使用して結果を抽出する必要があります

TryIntoのドキュメント