如何将切片转换为数组引用?

Posted

技术标签:

【中文标题】如何将切片转换为数组引用?【英文标题】:How to convert a slice into an array reference? 【发布时间】:2018-06-16 04:59:49 【问题描述】:

我有一个&[u8] 并想将其转换为&[u8; 3] 而无需复制。它应该引用原始数组。我该怎么做?

【问题讨论】:

[&x[0], &x[1], &x[2]]? 这是一个 [&u8; 3]. 你为什么需要那个? 另见相关但不同的How to get a slice as an array in Rust? 【参考方案1】:

从 Rust 1.34 开始,您可以使用 TryFrom / TryInto

use std::convert::TryFrom;

fn example(slice: &[u8]) 
    let array = <&[u8; 3]>::try_from(slice);
    println!(":?", array);


fn example_mut(slice: &mut [u8]) 
    let array = <&mut [u8; 3]>::try_from(slice);
    println!(":?", array);

【讨论】:

如果你将它传递给一个需要这样一个参数的函数,你也可以使用try_into().unwrap() 来避免写出数组类型的需要,如果你确定切片是足够大。【参考方案2】:

他们arrayref crate 实现了这个。

这是一个例子,你当然可以用不同的方式来使用它:

#[macro_use]
extern crate arrayref;

/// Get the first 3 elements of `bytes` as a reference to an array
/// **Panics** if `bytes` is too short.
fn first3(bytes: &[u8]) -> &[u8; 3] 
     array_ref![bytes, 0, 3]

【讨论】:

【参考方案3】:

再次强调,如果没有不安全的代码,这将无法完成,因为直到运行时您才知道切片中包含三个元素。

fn slice_to_arr3<T>(slice: &[T]) -> Option<&[T; 3]> 
    if slice.len() == 3 
        Some(unsafe  &*(slice as *const [T] as *const [T; 3]) )
     else 
        None
    

在实现const generics 之前,这不能在数组的长度上通用。

【讨论】:

我对“这不安全”的措辞持怀疑态度。这绝对是安全——只要你检查切片的长度。如果它实际上永远不可能是安全的,那么一开始就不应该写它。这是一个迂腐的论点,但对于 Rust 新手来说,“安全”的概念已经够混乱了,我觉得值得指出。 他的意思可能是“这不可能是不安全的”。 是的,我同意。也许更好的措辞是没有不安全的代码就无法完成 该逻辑不能“在没有不安全代码的情况下完成”,因为 stdlib 必然需要不安全代码,内部使用的所有内容都有。我认为正确的措辞是“这个问题没有完全的解决方案”;它的任何解决方案都必须是部分的,并以某种方式解释切片没有至少 3 个元素的错误情况。 @Zorf 我喜欢使用的措辞是区分 safesound。该代码不安全,因为您必须使用 unsafe 关键字,这是没有办法的。但这是合理的,因为我们检查切片的长度,编译器信任我们这样做。

以上是关于如何将切片转换为数组引用?的主要内容,如果未能解决你的问题,请参考以下文章

golang:将有序的数字切片转换为数字范围表示的字符串数组

如何在 Javascript/jQuery 中动态切片数组?

如何将键值映射转换为 int 切片 [关闭]

Go之切片

Golang 函数传参使用切片而不使用数组为什么?

Golang 函数传参使用切片而不使用数组为什么?