请考虑以下代码:
let mut val : u8 = 125;
let deltas : [i8; 4] = [5, -5, 5, 5];
let delta = select_current_delta(deltas);
val += delta;
这看起来很简单。我想根据某些标准增加或减少字节值(我有办法防止u8
值溢出。)
当然,这不会编译:
> rustc lala.rs
lala.rs:7:12: 7:17 error: mismatched types:
expected `u8`,
found `i8`
(expected u8,
found i8) [E0308]
lala.rs:7 val += delta;
^~~~~
咄!在Rust中,似乎禁止混合使用有符号和无符号类型。怎么样?
val = (val as i8 + delta) as u8;
这会编译,但是当我尝试运行它时......
> ./lala
thread '<main>' panicked at 'arithmetic operation overflowed', lala.rs:7
是的,i8
的最大值是125,加上5会溢出,即使u8
的值非常好。
我能够找到两种有效的解决方案:
val = (val as i16 + delta as i16) as u8;
// or
if delta < 0 { val -= (-delta) as u8 }
else { val += delta as u8}
这些似乎都不优雅。是否有一种惯用的方式将u8添加到i8?
答案 0 :(得分:7)
您可以这样做以避免溢出并包装添加:
val = (val as i8).wrapping_add(delta) as u8;
答案 1 :(得分:7)
是否有惯用的方式将
u8
添加到i8
?
向u8
(i8
)添加+
的问题是:结果应该是什么类型? u8
或i8
都不是更好,使用i16
虽然正确但可能会令人惊讶。
因此,目前,不支持混合积分操作数。惯用的方法是将两个操作数转换为公共类型,这也是结果的类型。这已经是你正在做的事情。
但是,
u8 += i8
是什么?
不幸的是,目前,这是u8 = u8 + i8
的糖,因此具有+
的所有限制,即使结果类型不是问题。
由于Rust的所有恼人的限制,它有一个RFC!这是PR #953: Overloaded Assignment Operations。此RFC处于最终评论期,因此很快就会做出决定,希望这意味着它将被接受,Rust将获得对混合积分分配操作的支持。
作为个人偏好,现在,我会选择:
val = (val as i16 + delta as i16) as u8;
避免了分支。