Rust:如何从有符号整数类型转换为更大的有符号整数类型*不*符号扩展

Edd*_*ett 1 casting rust

假设我们有一个i8要转换为i16 符号扩展的类型。

我们不能进行简单的as强制转换,因为这将导致扩展。

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

我们无法转换,因为类型的大小不同:

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

我想出的最好的方法是以下复杂的铸造链:

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

中间转换 tou8意味着转换到 au16将零扩展而不是符号扩展,然后从u16to转换i16就可以了,因为类型大小相同并且不需要扩展。

但一定有更好的办法吗?有没有?

mgo*_*tIH 6

请记住,对于这种情况(打印数字的位),您可以只进行无符号转换。

然而,一般来说,Rust 并不喜欢进行隐式转换,但你总是可以写

let n : i8 = -128;
let m : i32 = n as u8 as i32;
Run Code Online (Sandbox Code Playgroud)

一般来说,你几乎找不到比这更好的了,因为双重转换在更改指针类型等领域很常见。当您正在执行的操作可以安全地完成且没有任何缺点(除了可能有轻微的代码味道)时,还请考虑不要使用 unsafe。