This code works and prints "b":
此代码工作并打印“b”:
fn main() {
let s = "abc";
let ch = s.chars().nth(1).unwrap();
println!("{}", ch);
}
On the other hand, this code results in a mismatch type error.
另一方面,此代码会导致不匹配类型错误。
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
For some external reason, I have to use the u32
type for variable n
. How can I convert u32
to usize
and use it in nth()
?
由于一些外部原因,我不得不使用u32类型作为变量n。我如何将u32转换为usinze并在nth()中使用它?
更多回答
The most cautious thing you can do is to use TryFrom
and panic when the value cannot fit within a usize
:
你能做的最谨慎的事情是使用TryFrom,并在值不能适应一个usinze时惊慌失措:
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);
}
By blindly using as
, your code will fail in mysterious ways when run on a platform where usize
is smaller than 32-bits. For example, some microcontrollers use 16-bit integers as the native size:
通过盲目使用as,当在usinze小于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
}
For broader types of numeric conversion beyond u32
<-> usize
, refer to How do I convert between numeric types safely and idiomatically?.
有关u32<->usize之外更广泛的数字转换类型,请参阅如何安全且惯用地在数字类型之间转换?。
See also:
另请参阅:
The as
operator works for all number types:
as运算符适用于所有数字类型:
let ch = s.chars().nth(n as usize).unwrap();
Rust forces you to cast integers to make sure you're aware of signedness or overflows.
Rust强制您强制转换整数,以确保您知道有符号或溢出。
Integer constants can have a type suffix:
整数常量可以有类型后缀:
let n = 1u32;
However, note that negative constants, such as -1i32
is internally -
1i32
.
但是,请注意,负常数(如-1i32)在内部是-1i32。
Integer variables declared without an explicit type specification are shown as {integer}
and will be properly inferred from one of the method calls.
在没有显式类型规范的情况下声明的整数变量显示为{Integer},并且将从其中一个方法调用中正确推断。
We now have a pretty different answer when we try to compile your code, replacing the number 1
with a variable of type i32
:
现在,当我们试图编译代码时,我们有了一个完全不同的答案,将数字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();
|
It means that now the compiler recommends you to use n.try_into().unwrap()
that makes use of the trait TryInto
which in turn relies on TryFrom
and returns a Result<T, T::Error>
. That's why we need to extract the result with a .unwrap()
这意味着现在编译器建议您使用n.try_into().unwrap(),它利用了特性TryInto,该特性反过来依赖于TryFrom并返回Result
。这就是为什么我们需要使用.unwrap()提取结果
TryInto
documentation
TryInto文档
更多回答
I think before using TryFrom
, FOR SOME CASES, a developer could also use the From
trait (e.g. u32::from(n)
. This should issue an error at compile-time if the cast is not implemented in the Rust-Compiler. HOWEVER: As far as i can see, the From
trait for isize
and usize
is only implemented for u8 and u16 but are not checked depending on the platform (see doc.rust-lang.org/src/core/convert/num.rs.html#44 and doc.rust-lang.org/src/core/convert/num.rs.html#135). This could be an issue for 8-bit microcontrollers (not sure if Rust supports them)
我认为在使用TryFrom之前,在某些情况下,开发人员还可以使用From特性(例如u32::From(n))。如果未在Rust编译器中实现强制转换,则这将在编译时发出错误。HOWEVER:据我所见,isize和usize的From特性仅在u8和u16中实现,但根据平台的不同而未进行检查(请参阅doc.rust-lang.org/src/core/convert/num.rs.html#44和doc.rust-rang.org/src/core/convert/num.rs.html#135)。这可能是8位微控制器的问题(不确定rust是否支持它们)
@obraunsdorf linked to an existing answer that covers that, thanks.
@obraunsdorf联系到了一个现有的答案,谢谢。
To protect people who blindly copy&paste this answer: I think the answer from @Shepmaster (stackoverflow.com/a/55769098/1290383) should be the "accepted" answer. Someone might stumble across this answer here thinking that using as
is save for numeric casts but it's not.
为了保护那些盲目复制粘贴这个答案的人:我认为@Shepmaster(stackoverflow.com/a/55769098/1290383)的答案应该是“公认的”答案。有些人可能会在这里偶然发现这个答案,认为使用as是对数值强制转换的保存,但事实并非如此。
casts between integertypes are safe in the sense they produve deterministic results. Tgose results may not be what you want, but the same applies to nost numeric operations.
整数类型之间的强制转换是安全的,因为它们会产生确定性的结果。Tgose结果可能不是您想要的,但nost数字运算也是如此。
This is effectively already covered by an existing answer, as TryFrom
/ TryInto
are mirrors of each other.
这实际上已经被现有的答案所涵盖,因为TryFrom/TryInto是彼此的镜像。
我是一名优秀的程序员,十分优秀!