如何将不可变视图(切片?)作为八位字节借给矢量?

Gol*_*nks 3 type-conversion rust

我正在尝试使用UDP在网络上发送32位浮点数向量.该UdpSocket.send_to(buf, dst)方法接受一个8位uint切片.我想将它作为一个传递给它&[u8].我该如何做到这一点?我没有从API中找到任何相关的转换方法.

在这种情况下无需关心字节序.然而.

Vla*_*eev 8

首先,这些操作本质上是不安全的,因此不能在没有unsafe阻塞的情况下完成.

切片是一对(pointer, length),而你也能投射出原始指针某种类型的原始指针到另一种类型,您还需要调整长度,以保持所产生的切片有效.这可以这样做:

use std::raw::Slice;
use std::mem;

fn main() {
    let floats: Vec<f32> = vec![0.1, 2.3, 4.5, 6.7];
    let floats: &[f32] = floats.as_slice();

    let raw_floats: Slice<f32> = unsafe { mem::transmute(floats) };
    let raw_bytes: Slice<u8> = Slice {
        data: raw_floats.data as *const u8,
        len: raw_floats.len * mem::size_of::<f32>()
    };

    let bytes: &[u8] = unsafe { mem::transmute(raw_bytes) };

    println!("{}", bytes);
}
Run Code Online (Sandbox Code Playgroud)

(在这里试试)

当然,上面的大多数类型注释都是为了清楚起见.

您应该特别小心,以确保获得的&[u8]切片不会超过其原始数据所有者(在这种情况下为向量).如果你只是通过调用堆栈传递这个片段(你的用例 - 通过网络发送数据 - 似乎是这样),那么你没关系; 如果你需要从函数中返回这样的切片,你需要注意一生,尽管Rust类型/生命周期推断足够高,使它们几乎不可见.例如,从转换的一般方法&[T],以&[u8]看起来是这样的:

use std::raw::Slice;
use std::mem;

fn view_as_bytes<'a, T: Copy>(items: &'a [T]) -> &'a [u8] {  // '
    let raw_items: Slice<T> = unsafe { mem::transmute(items) };
    let raw_bytes = Slice {
        data: raw_items.data as *const u8,
        len: raw_items.len * mem::size_of::<T>()
    };
    let bytes: &[u8] = unsafe { mem::transmute(raw_bytes) };
    bytes
}

fn main() {
    let floats: Vec<f32> = vec![0.1, 2.3, 4.5, 6.7];
    let bytes = view_as_bytes(floats.as_slice());

    println!("{}", bytes);
}
Run Code Online (Sandbox Code Playgroud)

(在这里试试)

'a为了清晰起见,我添加了生命周期参数,但由于生命周期的限制,可以安全地省略它.

但是,如果您的数据是在函数内创建的,则不应从此函数返回任何切片.transmute()功能足够强大,但最终只能导致段错误.

  • 请考虑展示如何正确地做一生的事情.我会写一个`不安全的fn as_raw_bytes(s:&[f32]) - >&[u8]`依赖于生命周期省略规则.也许更好的想法是在这种情况下明确,因为它是一个不安全的函数,而不是编译错误,如果生命周期错误,你会陷入悬空指针的麻烦. (3认同)