Reputation: 3573
Suppose we have an i8
which we want to cast to an i16
without sign extension.
We can't do us a simple as
cast, as this will sign extend.
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.
But there must be a better way? Is there?
Upvotes: 1
Views: 3952
Reputation: 466
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
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).
Upvotes: 6