如何在u32和usize之间进行惯用转换?

时间:2017-04-30 09:09:36

标签: types rust type-conversion

此代码可以工作并打印" 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

出于某些外部原因,我必须将u32类型用于变量n。如何将u32转换为usize并在nth()中使用它?

3 个答案:

答案 0 :(得分:11)

as运算符适用于所有数字类型:

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

Rust会强制您投整整数,以确保您了解签名或溢出。

整数常量可以有一个类型后缀:

let n = 1u32;

但请注意,-1i32等负面常量位于内部- 1i32

在没有显式类型规范的情况下声明的整数变量显示为{integer},并将从其中一个方法调用中正确推断。

答案 1 :(得分:2)

您可以做的最谨慎的操作是使用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
}

答案 2 :(得分:1)

当我们尝试编译您的代码时,我们有一个截然不同的答案,将数字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();
  |    

这意味着现在编译器建议您使用利用特征TryInton.try_into().unwrap(),后者又依赖于TryFrom并返回Result<T, T::Error>。这就是为什么我们需要使用.unwrap()

提取结果的原因

TryInto documentation