1. 两种不同模式下的整形溢出
坑了个爹的,书上说的没理解清楚,在Rust程序语言设计中文版3.2中提到了,当使用--release参数进行发布模式构建时,Rust不会检测导致panic的整形溢出,这里需要分两种情况考虑:
- 编译期就可以发现的整形溢出
- 程序运行过程中会发生的整形溢出
1.1 编译阶段
如果是编译期能够确定会发生的整形溢出(程序1-1),无论是不是执行了--release
参数都会在构建阶段(cargo build
)发生报错
// 程序1-1
fn main() {
let i:u8 = 254;
let i = i + 4;
println!("{}!",i);
}
上述变量i
的类型为u8
类型,值的范围在(0..=255)
,
经过运算的结果最终的i
的值为258
,这个值在编译期已经可以检测到整形溢出,最终构建会报错如下:
-
debug
模式 -
release
模式这种编译期可以确定的溢出错误,两种模式下都会发生崩溃
1.2 运行阶段
在运行期发生的整形溢出(程序1-2),不会在build阶段报错
// 程序1-2
fn main() {
let i:u8 = 254;
for j in 0..=4 {
println!("{}!",i+j);
}
}
上述代码,只有在j>1
的情况下才会发生整形溢出,这种错误在编译期是发现不了的
-
debug
模式执行在不使用
--release
的时候,在运行阶段报错 -
release
模式在使用
--release
的情况下,溢出值对256进行了取模运算
1.3 说明
当使用--release
进行构建发布模式时,当检测到整形溢出,将会使用一种进制补码包裹(two’s complement wrapping)的操作。就是最终的计算出来的结果对2N取模。N
为类型的bit位,u8是8位,N=8
2 Rust对溢出的操作
摘自:数据类型 - Rust 程序设计语言 中文版 (rustwiki.org)
要显式处理溢出的可能性,可以使用标准库针对原始数字类型提供的以下一系列方法:
- 使用
wrapping_*
方法在所有模式下进行包裹,例如wrapping_add
- 如果使用
checked_*
方法时发生溢出,则返回None
值- 使用
overflowing_*
方法返回该值和一个指示是否存在溢出的布尔值- 使用
saturating_*
方法使值达到最小值或最大值这么处理,在debug模式下就不会panic
2.1 wrapping_*
当计算结果发生溢出执行取模操作(程序2-1)
// 2-1
fn main() {
let i:u8 = 254;
for j in 2..=4 {
println!("=======================");
println!("i+j={}!",i.wrapping_add(j));
println!("j-i={}!",j.wrapping_sub(i));
println!("j*i={}!",j.wrapping_mul(i));
println!("j/i={}!",j.wrapping_div(i));
}
}
结果如下:
那么问题来了,负数怎么取整?
标签:u8,wrapping,Rust,println,整形,溢出 From: https://www.cnblogs.com/ITY996/p/17811581.html