25.5 Casting and std::mem::transmute

Safe Rust allows only a limited set of casts (for example, certain integer-to-integer conversions). If you need to reinterpret a type’s bits as another type, though, you must use unsafe features.

Two main mechanisms are available:

  1. The as operator, covering certain built-in conversions.
  2. std::mem::transmute, which reinterprets the bits of a value as a different type without any runtime checks.

transmute essentially copies bits from one type to another. You must specify source and destination types of identical size; if they differ, the compiler will reject the code (unless you use specific nightly features, which is highly unsafe).

25.5.1 Example: Reinterpreting Bits with transmute

fn float_to_bits(f: f32) -> u32 {
    unsafe { std::mem::transmute::<f32, u32>(f) }
}

fn bits_to_float(bits: u32) -> f32 {
    unsafe { std::mem::transmute::<u32, f32>(bits) }
}

fn main() {
    let f = 3.14f32;
    let bits = float_to_bits(f);
    println!("Float: {}, bits: 0x{:X}", f, bits);

    let f2 = bits_to_float(bits);
    println!("Back to float: {}", f2);
}

Since transmute reinterprets bits without checking types, incorrect usage can easily result in undefined behavior. Often, safer alternatives (such as the built-in to_bits and from_bits methods for floats) are more appropriate.