我是否必须像下面的示例中那样对有符号整数的符号进行分支? (在实际程序中,y
的计算是将指向64K数组的索引更改为索引,而环绕操作是所需的行为)
fn main() {
let mut x: u16 = 100;
let y: i8 = -1;
//x += y;
if y < 0 {
x -= i8::abs(y) as u16;
} else {
x += i8::abs(y) as u16;
}
println!("{}", x);
}
答案 0 :(得分:1)
i8 as u16
这意味着您可以强制转换y as u16
,如果y
为负,则将变成一个二进制补码值,wraping_add将正确处理该值。
简而言之:按照@Veedrac所说。
fn main() {
let mut x: u16 = 100;
let y: i8 = -1;
x = x.wrapping_add(y as u16);
println!("{}", x);
}
答案 1 :(得分:0)
在真实程序中,
y
的计算是将指向64K数组的索引更改为索引,而回绕是所需的行为)
目前尚无共识,但我的建议是:向用户提供两个功能:
fn add(&mut self, index: u16) -> u16 { // return previous index why not
// ..
}
fn sub(&mut self, index: u16) -> u16 {
// ..
}
您还可以添加一个不应轻易使用的辅助功能:
fn offset(&mut self, offset: i16) -> u16 {
// ..
}
目的是,用户应该知道每当使用sub或add时,用户应该只管理未签名的类型。这个问题是基于观点的,所以我理解人们是否同意。
完整示例:
use std::mem;
#[derive(Debug, PartialEq, PartialOrd)]
struct MyIndex {
index: u16,
}
impl MyIndex {
fn new(index: u16) -> Self {
Self { index }
}
fn add(&mut self, index: u16) -> u16 {
let index = self.index.wrapping_add(index);
self.replace(index)
}
fn sub(&mut self, index: u16) -> u16 {
let index = self.index.wrapping_sub(index);
self.replace(index)
}
fn offset(&mut self, offset: i16) -> u16 {
if offset > 0 {
self.add(offset as u16)
} else {
self.sub(offset as u16)
}
}
fn replace(&mut self, index: u16) -> u16 {
mem::replace(&mut self.index, index)
}
}
fn main() {
let mut index = MyIndex::new(42);
let mut other_index = MyIndex::new(84);
let (x, first) = if index > other_index {
(index.index - other_index.index, true)
}
else {
(other_index.index - index.index, false)
};
// ...
if first {
index.sub(x);
}
else {
other_index.sub(x);
}
println!("{:?} {:?}", index, other_index);
index.sub(21);
println!("{:?}", index);
index.offset(-1);
println!("{:?}", index);
}