据我了解,[[T; 4]; 3]
和[T; 12]
在内存中具有相同的布局。在这些类型之间转换值的最佳方法是什么?我可以将引用转换为对另一个的引用吗?我可以避免复制所有元素吗?我需要unsafe
吗?
答案 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问题。也许您使用数据的方式可以改为不需要这个?