简体   繁体   中英

What is the difference between repr(C) and repr(rust)?

I am currently writing a Vulkan renderer and I just realized that I should only accept types that are repr(C) , but as far as I know there is no way to actually check that at compile time.

struct Vertex {
    x: f32,
    y: f32,
    b: Box<f32>
}

#[repr(C)]
struct Vertex2 {
    x: f32,
    y: f32,
    b: Box<f32>
}

fn to_bytes<T>(t: &T) -> &[u8]{
    let p: *const T = t;
    let p = p as *const u8;
    unsafe{
        std::slice::from_raw_parts(p, std::mem::size_of::<T>())
    }
}

fn main() {
    let v = Vertex{x: 42.0, y: 0.0, b: Box::new(42.0)};
    let v2 = Vertex2{x: 42.0, y: 0.0, b: Box::new(42.0)};
    println!("{:?}", to_bytes(&v));
    println!("{:?}", to_bytes(&v2));
}

Playground

After a few tries, I could finally see a difference between repr(c) and repr(rust) but only when I used a Box .

What is the difference between repr(C) and repr(rust) ? Can I assume that if a type only contains other POD types, then the layout will be the same as in C?

Example:

let slice = base.device
    .map_memory::<Vertex>(vertex_input_buffer_memory,
                          0,
                          vertex_input_buffer_info.size,
                          vk::MemoryMapFlags::empty())
    .unwrap();
slice.copy_from_slice(&vertices);

Source

I am filling a buffer that I hand to Vulkan, so I assume that the layout here probably matters.

The difference you see in the output of your program is not due to memory layout. Box<T> heap allocates and stores a pointer to the heap contents, so what you are printing is the pointer. As Box<T> doesn't perform any interning/object pooling, the two addresses are of course different. What's probably a bit confusing is that the addresses are so close to each other. I guess this has just something to do with jmalloc, the allocator Rust uses, which has densely packed pools for small allocations.

Can I assume that if a type only contains other POD types, then the layout will be the same as in C?

No. You pretty much can't assume anything about Rust's memory layout of types. This is intentionally not specified to allow for optimizations, such as field reordering. Even though right now , repr(Rust) matches repr(C) pretty closely, you can't assume that it will be like that forever.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM