Is it legal to cast a struct to an array?

喜欢而已 提交于 2020-12-06 04:14:20

问题


Consider the following:

// Just a sequence of adjacent fields of same the type
#[repr(C)]
#[derive(Debug)]
struct S<T> {
    a : T,
    b : T,
    c : T,
    d : T,
}

impl<T : Sized> S<T> {
    fn new(a : T, b : T, c : T, d : T) -> Self {
        Self {
            a,
            b,
            c,
            d,
        }
    }
    // reinterpret it as an array
    fn as_slice(&self) -> &[T] {
        unsafe { std::slice::from_raw_parts(self as *const Self as *const T, 4) }
    }
}

fn main() {
    let s = S::new(1, 2, 3, 4);
    
    let a = s.as_slice();
    
    println!("s :: {:?}\n\
              a :: {:?}", s, a);
}
  • Is this code portable?
  • Is it always safe to assume a repr(C) struct with fields of same type can be reinterpreted like an array? Why?

回答1:


Yes, it is safe and portable, except for very large T (fix below). None of the points listed in the safety section of the documentation for std::slice::from_raw_parts are a concern here:

  • The data pointer is valid for mem::size_of::<T>() * 4, which is the size of S<T>, and is properly aligned.

    • All of the items are in the same allocation object, because they are in the same struct.
    • The pointer is not null, because it is a cast from the safe &self parameter, and it is properly aligned, because S<T> has (at least) the alignment of T.
  • The data parameter definitely points to 4 consecutive initialized Ts, because S is marked #[repr(C)], and that is the behavior of C on all platforms (repr(Rust) makes no such guarantee).

  • The memory referenced is not mutated during the lifetime of the reference, which is guaranteed by the borrow checker.

  • The total size of the slice must not be greater than isize::MAX. The code does not check this, so it is technically a safety hole. To be sure, add a check to as_slice, before the unsafe:

    assert!(std::mem::size_of::<S<T>>() <= isize::MAX as _);
    

    The check will normally be optimized out.



来源:https://stackoverflow.com/questions/62240126/is-it-legal-to-cast-a-struct-to-an-array

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!