Issue with transmute


#1

Hi
I think I don’t understand how transmute works, can someone help me.

Here is an example:

use std::mem;

pub struct Foo {
     a: u8,
     b: u32,
 }

 impl Foo {
     fn from_bytes(bytes: [u8; 5]) -> Foo {
         unsafe {
             mem::transmute(bytes)
         }
     }
}
error: transmute called with differently sized types: [u8; 5] (40 bits) to Foo (64 bits) [--explain E0512]
  --> <anon>:15:14
15 |>              mem::transmute(bytes)
   |>              ^^^^^^^^^^^^^^

error: aborting due to previous error

I don’t understand why Foo is not 40 bits.Is there something obvious I can’t see?


#2

The elements of the struct are padded such that each starts at an address matching that element type’s alignment. For more information on padding and alignment, see http://www.catb.org/esr/structure-packing/#_structure_alignment_and_padding . You can force a packed representation using #[repr(packed)]


#3

Literally the case: padding.

Honestly, you shouldn’t be touching transmute unless you understand what’s really going on under the covers. Not only do you have the size wrong, you shouldn’t ever transmute a non-#[repr(C/packed)] struct like that (…except for cases where it turns out to be OK). It’s even endian-dependent, which can end up being a nasty surprise for someone down the road.

If you want to convert raw bytes into other values, you should probably look to the byteorder crate, which provide a safe interface for doing this.


#4

Thank you both of you!


#5

Maybe this Thread gives you some more ideas to solve your specific case: Best way to get the 3 bytes of a small u32?