暂时将[u8]转换为[u16]

时间:2015-11-28 07:30:23

标签: arrays casting rust unsafe

我有[u8; 16384]u16。我如何“暂时转换”数组,以便我可以同时设置两个u8,第一个到最低有效字节,第二个到最高有效字节?

3 个答案:

答案 0 :(得分:11)

明显,安全和便携的方式就是使用数学。

fn set_u16_le(a: &mut [u8], v: u16) {
    a[0] = v as u8;
    a[1] = (v >> 8) as u8;
}

如果你想要一个更高级别的界面,可以使用byteorder箱来实现这一目的。

您绝对应该使用transmute[u8]变成[u16],因为这并不能保证任何关于字节顺序。

答案 1 :(得分:3)

As DK suggests,您可能不应该使用unsafe代码来重新解释内存......但如果您愿意,也可以。

如果你真的想走这条路,你应该知道几个陷阱:

  • 您可能遇到对齐问题。如果您只是从某个位置获取&mut [u8]并将其转换为&mut [u16],则可能会引用一些未正确对齐的内存区域作为{{1}进行访问}}。根据您运行此代码的计算机,这种未对齐的内存访问可能是非法的。在这种情况下,程序可能会以某种方式中止。例如,CPU可以生成某种信号,操作系统会响应该信号以终止进程。
  • 这将是不便携的。即使没有对齐问题,您也可以在不同的机器上获得不同的结果(小型机器与大型机器)。

如果你可以切换它(创建一个u16数组并在字节级暂时处理它),你就可以解决潜在的内存对齐问题:

u16

在大端机器上,此功能无法满足您的需求;你想要一个小端字节顺序。您只能将其用作小端机器的优化,并且需要坚持使用像DK这样的大型或混合端机器的解决方案。

答案 2 :(得分:2)

slice::align_toslice::align_to_mut自Rust 1.30起是稳定的。这些函数处理sellibitze引起的对齐问题。

大端和小端问题仍然是您要担心的问题。您可能可以使用u16::to_le之类的方法来帮助您。但是,我无法使用大端计算机进行测试。

fn example(blob: &mut [u8; 16], value: u16) {
   // I copied this example from Stack Overflow without providing 
   // rationale why my specific case is safe.
   let (head, body, tail) = unsafe { blob.align_to_mut::<u16>() };

   // This example simply does not handle the case where the input data
   // is misaligned such that there are bytes that cannot be correctly
   // reinterpreted as u16.
   assert!(head.is_empty());
   assert!(tail.is_empty());

   body[0] = value
}

fn main() {
   let mut data = [0; 16];
   example(&mut data, 500);
   println!("{:?}", data);
}