请考虑以下代码:
let mut val : u8 = 125;
let deltas : [i8; 4] = [5, -5, 5, 5];
let delta = select_current_delta(deltas);
val += delta;
Run Code Online (Sandbox Code Playgroud)
这看起来很简单.我想根据某些标准增加或减少字节值(我有办法防止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;
^~~~~
Run Code Online (Sandbox Code Playgroud)
咄!在Rust中,似乎禁止混合使用有符号和无符号类型.这个怎么样?
val = (val as i8 + delta) as u8;
Run Code Online (Sandbox Code Playgroud)
编译,但当我尝试运行它...
> ./lala
thread '<main>' panicked at 'arithmetic operation overflowed', lala.rs:7
Run Code Online (Sandbox Code Playgroud)
是的,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}
Run Code Online (Sandbox Code Playgroud)
这些似乎都不优雅.是否有一种惯用的方法将i8添加到i8?
是否有一种惯用的方式来添加
u8一个i8?
u8向a i8(with +)添加a的问题是:结果应该是什么类型?无论u8或者i8是更好的,并且使用i16而正确的可能会是令人惊讶的.
因此,目前不支持混合积分操作数.惯用的方法是将两个操作数转换为公共类型,这也是结果的类型.这已经是你正在做的事情.
但是,那是
u8 += i8什么?
不幸的是,目前,这是糖u8 = u8 + i8,因此具有所有限制,+即使结果类型不是问题.
由于Rust的所有烦人的限制,它有一个RFC!这是PR#953:重载分配操作.此RFC处于最终评论期,因此很快就会做出决定,希望这意味着它将被接受,Rust将获得对混合积分分配操作的支持.
作为个人偏好,现在,我会去:
val = (val as i16 + delta as i16) as u8;
Run Code Online (Sandbox Code Playgroud)
这避免了分支.
您可以这样做以避免溢出并包装添加:
val = (val as i8).wrapping_add(delta) as u8;
Run Code Online (Sandbox Code Playgroud)