正如标题所示,我将如何做到这一点?
UICollectionView
编译器错误
fn foo(array: &[u32; 10]) -> &[u32; 5] {
&array[0..5]
}
答案 0 :(得分:2)
arrayref实现了一个安全的接口来执行此操作,使用宏(当然还有编译时常量切片边界)。
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开始的两个字节组成的片段进行数组引用。除了语法(不如切片好),它基本上与切片方法相同。但是,这段代码明确表示在调用者和函数签名中都需要精确的两个字节。
答案 1 :(得分:1)
仅使用安全的Rust不可能做到这一点。要了解原因,了解如何实现这些类型非常重要。保证数组具有N个初始化元素。它不能变小或变大。在编译时,这些保证允许删除数组的大小方面,并且该数组仅占用N * sizeof(元素)空间。
这意味着[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中以不安全的方式执行此操作,所以我将提供代码based on the standard library implementation:
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);
}