【发布时间】:2023-03-22 22:33:01
【问题描述】:
在进行带有溢出检查的整数运算时,计算通常需要组合多个算术运算。在 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))
}
但是,这告诉编译器为每个基本操作生成一个分支。我遇到了使用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)
}
}
不考虑溢出继续计算并使用按位或聚合溢出标志可确保在整个评估中最多执行一个分支(前提是overflowing_* 的实现生成无分支代码)。这种优化友好的方法比较麻烦,在处理中间值时需要谨慎。
有没有人了解 Rust 编译器如何在各种 CPU 架构上优化上述任一模式,以判断显式展开是否值得,尤其是对于更复杂的表达式?
【问题讨论】:
-
不太清楚你的问题是什么。理想的答案包含什么?
-
我希望人们提出轶事,或者更好地观察一致的编译器行为,当展开的方法最终比
Option更符合人体工程学的代码好得多时。
标签: rust integer-overflow integer-arithmetic