我怎样才能有效地实施:
fn shorten(arg: [u8; 32]) -> [u8; 30] {
???
}
Run Code Online (Sandbox Code Playgroud)
它会丢弃最后两个字节吗?
显然我可以使用 for 循环,并在堆栈上创建一个新的较短数组。
编译器似乎有机会离开堆栈并[u8; 32]仅使用它[u8; 30]的。
通常我会使用切片,但这里我需要返回一个较短的数组。
这是直接回答并没有多大价值的问题之一。但让我们从直接的答案开始:您可以将函数实现为
fn shorten(arg: [u8; 32]) -> [u8; 30] {
std::array::from_fn(|i| arg[i])
}
// or
fn shorten(arg: [u8; 32]) -> [u8; 30] {
arg[..30].try_into().unwrap()
}
// or
fn shorten(arg: [u8; 32]) -> [u8; 30] {
let mut ret = [0; 30];
ret.copy_from_slice(&arg[..30]);
ret
}
// or
fn shorten(arg: [u8; 32]) -> [u8; 30] {
let mut ret = [0; 30];
for i in 0..30 {
ret[i] = arg[i];
}
ret
}
Run Code Online (Sandbox Code Playgroud)
忽略函数调用的脚手架,这些都优化至四个 x86 指令。
movups xmm0, xmmword ptr [rsi]
movups xmm1, xmmword ptr [rsi + 14]
movups xmmword ptr [rdi + 14], xmm1
movups xmmword ptr [rdi], xmm0
Run Code Online (Sandbox Code Playgroud)
(看到那里的诡计,重叠加载/存储?聪明。-.- )
现在,对于答案的非直接部分:问题是孤立地看待是没有意义的fn shorten:
shorten是它自己的函数并返回一个owned [u8; 30],它就必须复制一份,因为返回值是与参数不同的值。它不能返回指向参数的指针,因为签名承诺它返回一个值。shorten很短,LLVM 肯定会内联它。然后的问题是 LLVM 是否可以弄清楚,无论使用 的结果,shorten也会对[u8; 32]. 它是否可以做到这一点与您提供的信息无关。最后shorten是四个 x86 指令。您是否真的处于这样的状态:这占用了您执行时间的很大一部分?