8、溢出

溢出

rust中的整型有范围,这从一开始就清楚的

比如u8类型的范围就是0~255,那么如果运算时超出了这个范围,就会发生溢出

溢出在rust中是一个error,如果在C/C++等语言当中往往会被直接忽略掉,但是rust很安全,他不允许溢出随便发生

如果运算的结果 > 类型::MAX,则称为上溢,如果 < 类型::MIN,则称为下溢

无自动类型转换

在其它语言中,如果发生了溢出,可能存在自动类型转换以防止溢出的发生,python支持大整数,无限精度,其他也没有什么语言可以非常好的处理溢出了

rust的理念就是,不能完全解决这个问题,那就避免这个问题的发生

所以rust自然不支持这种东西

解决方案

我们有两种方案可以实现较好的处理溢出

  • 拒绝操作
  • 提出一个更好的方案处理预期外的整数类型

拒绝操作

最保守的方式就是rust默认的方式,一旦发生溢出,那么直接终止程序的执行,这个过程通过panic来实现,前面也接触到了这个panic

image-20250830221108212

提出一个“明智”的结果

当算术操作的结果发生溢出时,可以选择环绕(warp around)

这其实就相当于C/C++里面默认的溢出处理方式,比如u8类型,255+1=0,MAX+1=MIN,这样子

溢出检查

rust允许选择整数溢出发生时使用的方法,该行为由 overflow-checks 配置文件设置

如果将 overflow-checks 的值被置为 true ,那么整数溢出时,rust将在运行时发生panic,如果将 overflow-checks 的值被置为 false ,那么整数溢出时,rust将 (环绕)warp around

然后就是,详细了解一下配置文件(Profiles)

Profiles(配置文件)

配置文件时一组配置选项,可以自定义Rust代码编译方式

Cargo提供了四种配置:dev,release,test和bench

dev: 运行cargo buildcargo runcargo test等命令时,都是以dev配置模式运行

release: 发布release版本时,要通过添加—release以构建release发布版,即cargo build --release

dev模式,编译起来很快,但是性能不佳,是专门用来开发与调试的。release模式在编译时,会进行漫长的优化,以确保代码的执行效率,所以编译过程会比较漫长

test: test配置是在执行cargo test时默认选择的配置,test配置继承于dev配置

bench: bench配置是在执行cargo bench时默认选择的配置,bench配置继承于release配置

总结:

dev 适用于迭代开发与调试
release 优化的生产版本
test 单元测试与集成测试
bench 性能基准测试

overflow-checks

一般情况下,overflow-checks的配置是,对于dev模式是true,对于release模式是false

如果不是极端的要求性能的场景,官方还是建议我们把溢出检查都打开

不过有个问题,如果我想在某些地方启用溢出检查,某些地方不想启用溢出检查的话,这个全局配置就很不适用了

所以Rust提供了一种方法来实现自定义是否对某个细微的地方启用溢出检查

warpping_methods

比如使用warpping_add就可以实现主动关闭溢出检查的加法了

let x = 255u8;
let y = 1u8;
let sum = x.wrapping_add(y);
assert_eq!(sum, 0);

练习

题目很简单,就是实现阶乘的无溢出检测

RustRover的代码提示挺好的,直接提示除了warpping方法有warpping_mul

pub fn factorial(n: u32) -> u32 {
    let mut result: u32 = 1;
    for i in 1..=n {
        result = result.wrapping_mul(i);
    }
    result
}

这一节的学习就先到这里了

阅读剩余
THE END