如何安全地和惯用地在数字类型之间进行转换?

时间:2015-02-02 07:50:34

标签: casting rust numbers

  

编者注:此问题来自1.0之前的Rust版本,并引用了Rust 1.0中不存在的一些项目。答案仍然包含有价值的信息。

从({)1 usize转换为u32的惯用方法是什么?

例如,使用4294967295us as u32进行投射并Rust 0.12 reference docs on type casting

  

可以将数值转换为任何数字类型。原始指针值可以转换为任何整数类型或原始指针类型。任何其他演员表都不受支持,无法编译。

但是4294967296us as u32会静默溢出并给出0的结果。

我发现ToPrimitiveFromPrimitive提供了很好的功能,例如to_u32() -> Option<u32>,但它们被标记为不稳定:

  

#[unstable(feature = "core", reason = "trait is likely to be removed")]

在数字(和指针)类型之间进行转换的惯用(和安全)方式是什么?

依赖于平台的isize / usize大小是我提出此问题的原因之一 - 原始方案是我想要从u32转换为{{ 1}}所以我可以用usize表示一棵树(例如Vec<u32>,然后得到节点2的祖父将是let t = Vec![0u32, 0u32, 1u32]),我想知道它会如何失败如果t[t[2us] as usize]小于32位。

1 个答案:

答案 0 :(得分:17)

ToPrimitive / FromPrimitive

RFC 369, Num Reform, states

  

理想情况下,[{1]} [...]将全部删除,以支持使用类似C的枚举的更有原则的方式

与此同时,这些特征仍然存在于num crate

没有特征的交易

从完全适合另一个

的类型

这里没问题。使用ToPrimitive明确表示不会发生任何损失:

From

您可以选择使用fn example(v: i8) -> i32 { i32::from(v) // or v.into() } ,但建议您在不需要时使用它(见下文):

as

从一种不完全适合另一种

的类型

没有一种方法可以理解 - 你要问的是如何在一个空间中放置两个东西。一个很好的初步尝试是在值适合时使用fn example(v: i8) -> i32 { v as i32 } - Option,否则使用Some。然后,您可以根据需要使程序失败或替换默认值。

自Rust 1.34起,您可以使用TryFrom

None

在此之前,您必须自己编写类似的代码:

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会无声地溢出并给出0

的结果

转换为较小的类型时,4294967296us as u32只取数字的低位,忽略高位,包括符号:

as