正如标题所写的,我该怎么做呢?
fn foo(array: &[u32; 10]) -> &[u32; 5] {
&array[0..5]
}编译器错误
error[E0308]: mismatched types
--> src/main.rs:2:5
|
2 | &array[0..5]
| ^^^^^^^^^^^^ expected array of 5 elements, found slice
|
= note: expected type `&[u32; 5]`
= note: found type `&[u32]`发布于 2016-11-08 14:24:33
稳定锈蚀
仅仅使用安全锈是不可能做到这一点的。要理解为什么,重要的是要了解这些类型是如何实现的。保证数组具有N个初始化元素。它不能变小或变大。在编译时,这些保证允许删除数组的大小方面,并且数组只占用N* size of (元素)空间。
这意味着[T; N]和[T; M]是不同的类型(当N != M时),您不能将一个引用转换为另一个引用。
惯用的解决方案是使用一个片段来代替:
fn foo(array: &[u32; 10]) -> &[u32] {
&array[0..5]
}切片包含指向数据和数据长度的指针,从而将该逻辑从编译时移动到运行时。
夜间锈病
您可以执行运行时检查切片是否正确的长度,并在一步内将其转换为数组:
#![feature(try_from)]
use std::convert::TryInto;
fn foo(array: &[u32; 10]) -> &[u32; 5] {
array[0..5].try_into().unwrap()
}
fn main() {}不安全锈病
因为有人可能希望在早期版本的Rust中以不安全的方式这样做,所以我将给出代码基于标准库的实现
fn foo(array: &[u32; 10]) -> &[u32; 5] {
let slice = &array[0..5];
if slice.len() == 5 {
let ptr = slice.as_ptr() as *const [u32; 5];
unsafe { &*ptr }
} else {
panic!("Needs to be length 5")
}
}
fn main() {
let input = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
let output = foo(&input);
println!("{:?}", output);
}发布于 2016-11-08 21:14:48
列瑞瑞使用宏(当然还有编译时常量切片边界)实现了执行此操作的安全接口。
他们的自述解释
arrayref的目标是在参数必须具有给定大小的情况下,有效地使用涉及数组引用而不是切片的API。
和
let addr: &[u8; 16] = ...;
let mut segments = [0u16; 8];
// array-based API with arrayref
for i in 0 .. 8 {
segments[i] = read_u16_array(array_ref![addr,2*i,2]);
}在这里,
array_ref![addr,2*i,2]宏允许我们对一个从2*i开始的由两个字节组成的切片进行数组引用。除了语法(不像切片那样好)之外,它与切片方法本质上是一样的。但是,这段代码明确说明了调用方和函数签名中都需要精确的两个字节。
https://stackoverflow.com/questions/40488690
复制相似问题