简体   繁体   English

Rust:如何从签名的 integer 类型转换为更大的签名 integer 类型 *无*符号扩展

[英]Rust: How to cast from a signed integer type to a larger signed integer type *without* sign extension

Suppose we have an i8 which we want to cast to an i16 without sign extension.假设我们有一个i8 ,我们想在没有符号扩展的情况下将其转换为i16

We can't do us a simple as cast, as this will sign extend.我们不能做一个简单as cast,因为这会扩展。

println!("{:b}", -128i8); // 10000000 <- we want this zero-extended in an i16.
println!("{:b}", -128i8 as i16);  // 1111111110000000 sign extended :(

We cannot transmute, because the types are of different size:我们无法转换,因为类型的大小不同:

println!("{:b}", unsafe {mem::transmute::<_, i16>(128i8)});
// ^ error[E0512]: cannot transmute between types of different sizes, or dependently-sized types :(

The best I've come up with is the following convoluted casting chain:我想出的最好的是以下复杂的铸造链:

println!("{:b}", -128i8 as u8 as u16 as i16); // 10000000 :), but :( because convoluted.

The intermediate cast to u8 means that casting up to a u16 will zero-extend instead of sign extend, then casting from u16 to i16 is fine, as the types are the same size and no extension is required.u8的中间转换意味着转换到u16将零扩展而不是符号扩展,然后从u16转换到i16很好,因为类型的大小相同并且不需要扩展。

But there must be a better way?但一定有更好的方法吗? Is there?在那儿?

Keeping in mind that for this case (printing the number's bits) you can just do the unsigned conversion.请记住,对于这种情况(打印数字的位),您可以只进行无符号转换。

However in general Rust doesn't really like doing implicit conversions, but you can always write但是一般 Rust 并不喜欢进行隐式转换,但你总是可以写

let n : i8 = -128;
let m : i32 = n as u8 as i32;

You pretty much can't get better than this in general, as double casting is common in fields like changing pointer's types.一般来说,你几乎没有比这更好的了,因为双重转换在更改指针类型等领域很常见。 Also consider not using unsafe when the operation you are doing can be done safely without downsides (aside from maybe a slight code smell).如果您正在执行的操作可以安全地完成而没有缺点(除了可能有轻微的代码气味),也请考虑不要使用 unsafe 。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM