转换[[T;]的最佳方法是什么? 4]; 3]成[T; 12]?

时间:2016-12-13 01:30:36

标签: multidimensional-array rust unsafe

据我了解,[[T; 4]; 3][T; 12]在内存中具有相同的布局。在这些类型之间转换值的最佳方法是什么?我可以将引用转换为对另一个的引用吗?我可以避免复制所有元素吗?我需要unsafe吗?

2 个答案:

答案 0 :(得分:9)

是的,您可以使用mem::transmute将对[[T; 4]; 3]的引用转换为[T; 12]的引用,但仅使用不安全的代码。最好将它包装在一个函数中,以便为结果引用赋予适当的生命周期,否则transmute将使得获得具有比引用应具有的更长生命周期的引用成为可能。

fn convert<'a>(a: &'a [[u8; 4]; 3]) -> &'a [u8; 12] {
    unsafe { std::mem::transmute(a) }
}

由于终身省略规则,这可以缩短:

fn convert(a: &[[u8; 4]; 3]) -> &[u8; 12] {
    unsafe { std::mem::transmute(a) }
}

虽然在处理不安全的代码时,我会理解您是否更喜欢更明确的版本!

答案 1 :(得分:3)

免责声明:对于Rust的低级别方面我还不是很好,我不知道在低级Rust中被认为是什么“好习惯”。这里给出的建议可能不是好主意。我把它们放在这里是因为......好吧,它们起作用了。

You could transmute them。问题是它将是一个副本,文档说它相当于wrap_content调用。这不是你想要的,但无论如何它都在这里:

memcpy

您的其他选择is to work with a raw pointer

fn main() {
    let a: [[u8; 4]; 3] = [[1, 2, 3, 4], [1, 2, 3, 4], [1, 2, 3, 4]];
    let b: [u8; 12] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12];

    println!("a: {:?}", a);
    println!("b: {:?}", b);

    let c = unsafe { std::mem::transmute::<[[u8; 4]; 3], [u8; 12]>(a) };

    println!("c: {:?}", c);
}

也不是特别好。

指针也可以是指向同一类型的指针或可变指针(因为fn main() { let a: [[u8; 4]; 3] = [[1, 2, 3, 4], [1, 2, 3, 4], [1, 2, 3, 4]]; let b: [u8; 12] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]; println!("a: {:?}", a); println!("b: {:?}", b); let c = &a as *const _ as *const [u8; 12]; // Or it can be this: let c = &mut a as *mut [[u8; 4]; 3]; for i in 0..12 { let p = c as *const u8; let v = unsafe { *p.offset(i) }; println!("{}", v); } } 可以转换为&mut T),上面的代码完全相同(使用*mut T标记为可变的):

a

我确实想知道这是否是一个XY问题。也许您使用数据的方式可以改为不需要这个?

相关问题