据我了解,在内存中,
[[T;4];3]
和[T;12]
具有相同的布局。如何在这些类型之间转换值?我能将一个引用转换成另一个引用吗?我能避免复制所有元素吗?需要使用unsafe
吗?[[T;4];3]
和[T;12]
具有相同的布局。如何在这些类型之间转换值?我能将一个引用转换成另一个引用吗?我能避免复制所有元素吗?需要使用unsafe
吗?[[T; 4]; 3]
的引用转换为对[T; 12]
的引用,但只能使用不安全代码,使用mem::transmute
。最好将其包装在一个函数中,以便分配适当的生命周期给结果引用,否则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) }
}
免责声明:我对Rust的低级方面并不是很擅长,不知道在低级Rust中什么被认为是“良好的实践”。这里给出的建议可能不是好主意。但我还是把它们放在这里,因为......它们有效。
你可以转换它们。问题是它会产生一份副本,文档说这相当于一个memcpy
调用。这不是你想要的,但它在这里:
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
)。let c = &mut a as *mut [[u8; 4]; 3];
我想知道这是否是一个XY问题。也许您处理数据的方式可以改变,不需要这个功能?