将i8添加到i8的惯用方法

Tom*_*omo 7 rust

请考虑以下代码:

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?

Mat*_* M. 8

是否有一种惯用的方式来添加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)

这避免了分支.


eul*_*isk 7

您可以这样做以避免溢出并包装添加:

val = (val as i8).wrapping_add(delta) as u8;
Run Code Online (Sandbox Code Playgroud)

在这里查看所有算术运算