如何在 u32 和 usize 之间进行惯用转换?
Posted
技术标签:
【中文标题】如何在 u32 和 usize 之间进行惯用转换?【英文标题】:How to idiomatically convert between u32 and usize? 【发布时间】:2017-09-28 00:31:14 【问题描述】:此代码有效并打印“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()
中使用?
【问题讨论】:
将usize
转换为u32
或反之亦然有哪些常见用例?
【参考方案1】:
as
运算符适用于所有数字类型:
let ch = s.chars().nth(n as usize).unwrap();
Rust 强制你转换整数以确保你知道有符号或溢出。
整数常量可以有类型后缀:
let n = 1u32;
但是,请注意负常数,例如 -1i32
在内部是 -
1i32
。
在没有明确类型说明的情况下声明的整数变量显示为integer
,并且将从方法调用之一正确推断。
【讨论】:
为了保护盲目复制和粘贴此答案的人:我认为@Shepmaster (***.com/a/55769098/1290383) 的答案应该是“已接受”的答案。有人可能会在这里偶然发现这个答案,认为使用as
可以节省数字转换,但事实并非如此。【参考方案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
对于u32
以外的更广泛的数字转换类型 usize
,请参阅How do I convert between numeric types safely and idiomatically?。
【讨论】:
我认为在使用TryFrom
之前,对于某些情况,开发人员还可以使用From
特征(例如u32::from(n)
。如果演员表不是,这应该会在编译时发出错误在 Rust 编译器中实现。但是:据我所见,isize
和 usize
的 From
特征仅针对 u8 和 u16 实现,但根据平台不进行检查(参见 doc.rust-lang.org/src/core/convert/num.rs.html#44 和doc.rust-lang.org/src/core/convert/num.rs.html#135)。这可能是 8 位微控制器的问题(不确定 Rust 是否支持它们)
@obraunsdorf 链接到涵盖该问题的现有答案,谢谢。【参考方案3】:
当我们尝试编译您的代码时,我们现在有一个完全不同的答案,将数字 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();
|
这意味着现在编译器建议您使用 n.try_into().unwrap()
,它利用了 TryInto
特性,而 TryInto
又依赖于 TryFrom
并返回 Result<T, T::Error>
。这就是为什么我们需要用.unwrap()
提取结果
TryInto
documentation
【讨论】:
这实际上已经被existing answer 覆盖,因为TryFrom
/ TryInto
是彼此的镜像。以上是关于如何在 u32 和 usize 之间进行惯用转换?的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 wstring_convert 在 utf16 和 utf32 之间进行转换?
如何在 C++11 中将 std::string 转换为 std::u32string?
如何使用 ARM NEON 内在函数将 u8 掩码转换为 u32 掩码?