简体   繁体   English

repr(C)和repr(rust)有什么区别?

[英]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. 我正在编写一个Vulkan渲染器,我刚刚意识到我应该只接受repr(C)类型,但据我所知,在编译时无法实际检查它。

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 . 经过几次尝试,我终于可以看到repr(c)repr(rust)之间的区别,但只有当我使用Box

What is the difference between repr(C) and repr(rust) ? repr(C)repr(rust)什么区别? Can I assume that if a type only contains other POD types, then the layout will be the same as in C? 我可以假设如果一个类型只包含其他POD类型,那么布局将与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. 我正在填写一个缓冲区,我交给Vulkan,所以我认为这里的布局可能很重要。

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. Box<T>堆分配并存储指向堆内容的指针,因此您要打印的是指针。 As Box<T> doesn't perform any interning/object pooling, the two addresses are of course different. 由于Box<T>不执行任何实习/对象池,因此这两个地址当然是不同的。 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. 这只与jmalloc有关,这是分配器Rust使用的,它有用于小分配的密集池。

Can I assume that if a type only contains other POD types, then the layout will be the same as in C? 我可以假设如果一个类型只包含其他POD类型,那么布局将与C中的相同吗?

No. You pretty much can't assume anything about Rust's memory layout of types. 不,你几乎不能假设Rust的类型内存布局。 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. 即使现在repr(Rust)repr(C)非常接近,你也不能认为它会永远像那样。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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