在执行带有溢出检查的整数算术时,计算通常需要组合多个算术运算。在 Rust 中链接检查算术的一种直接方法是使用checked_*
方法和Option
链接:
fn calculate_size(elem_size: usize,
length: usize,
offset: usize)
-> Option<usize> {
elem_size.checked_mul(length)
.and_then(|acc| acc.checked_add(offset))
}
Run Code Online (Sandbox Code Playgroud)
但是,这告诉编译器为每个基本操作生成一个分支。我遇到了一种使用overflowing_*
方法更展开的方法:
fn calculate_size(elem_size: usize,
length: usize,
offset: usize)
-> Option<usize> {
let (acc, oflo1) = elem_size.overflowing_mul(length);
let (acc, oflo2) = acc.overflowing_add(offset);
if oflo1 | oflo2 {
None
} else {
Some(acc)
}
}
Run Code Online (Sandbox Code Playgroud)
不考虑溢出而继续计算并使用按位 OR 聚合溢出标志可确保在整个评估中最多执行一个分支(前提是overflowing_*
生成无分支代码的实现)。这种优化友好的方法更麻烦,并且在处理中间值时需要谨慎。
有没有人有过 Rust 编译器如何在各种 CPU 架构上优化上述任一模式的经验,以判断显式展开是否值得,尤其是对于更复杂的表达式?