I've been porting some C code as an exercise as someone wrote a C function that's apparently faster than what I use at work.
I ported the C function to Rust, and when I started running tests on the output, I was getting a different result.
I used c2rust to transpile the C code, and then carefully debugged my Rust version and the transpiled code. I found where my code is wrong. I excluded the C code or the full Rust output as I was able to minimise the code. See below.
/// This matches what the C code does
pub fn cast(bytes: [u8; 32]) -> u32 {
let x = unsafe { *(&bytes[0] as *const u8 as *mut u32) };
x.swap_bytes()
// x
}
/// This doesn't match what the C code does
pub fn cast2(bytes: [u8; 32]) -> u32 {
let x = bytes[0] as u32;
x.swap_bytes()
// x
}
I understand the code to take a u8, cast it to u32 and then return (x as u32).swap_bytes()
.
What's confusing however is that (bytes[i] as u32).swap_bytes()
returns a different output to the one where we cast the reference to a pointer.
Is there something basic that I am missing?
Here's a repro: Compiler Explorer
Running the code on the playground shows this behaviour. Rust Playground. The below will output different values despite accessing the same value from the array.
fn main() {
let bytes = [1u8; 1];
let b = unsafe {*(&bytes[0] as *const u8 as *mut u32) };
dbg!(b, b.swap_bytes());
let bytes = [1u8; 32];
let b = unsafe {*(&bytes[0] as *const u8 as *mut u32) };
dbg!(b, b.swap_bytes());
}
With the output
[src/main.rs:4] b = 12289
[src/main.rs:4] b.swap_bytes() = 19922944
[src/main.rs:8] b = 16843009
[src/main.rs:8] b.swap_bytes() = 16843009