问题描述
我一直在逐步阅读《编程 Rust》这本书,想观察两个补码包装,代码很简单:
fn main() {
let mut x: u8 = 255;
println!("the value of x is {}",x) ;
x = 255 + 1 ;
println!("The value of x Now is {}",x) ;
}
当我按照指南尝试使用 Cargo 编译它时,我运行 货物构建--发布 书中说将让它在没有溢出保护的情况下编译,但它不会编译。我收到保护错误
| 6 | x = 255 + 1 ;
| ^^^^^^^^^^^^ 尝试计算u8::MAX + 1_u8
,这会溢出
你能解释一下我做错了什么吗?
解决方法
我相信在运行时不会动态检查该值(它不会 panic
并且会溢出),但在编译时仍会静态检查(如果可能)。
在这种情况下,编译器能够在编译时确定您要执行的操作并阻止您执行此操作。
也就是说,如果您查看编译器输出,您可以看到以下消息:
注意:#[deny(arithmetic_overflow)]
默认开启
无论优化级别如何,您都会看到此消息。
如果您想观察溢出,请将以下 inner attribute
放在源文件的顶部。
#![allow(arithmetic_overflow)]
或者,如果您直接使用 rustc
进行编译,则可以传递以下标志:
-O -A arithmetic_overflow
rustc
文档显示以下 lint 默认处于启用状态(无论优化级别如何)
- ambiguous_related_items
- arithmetic_overflow
- conflicting_repr_hints
- const_err
- ill_formed_attribute_input
- incomplete_include
- invalid_type_param_default
- macro_expanded_macro_exports_accessed_by_absolute_paths
- missing_fragment_specifier
- mutable_transmutes
- no_mangle_const_items
- order_dependent_trait_objects
- overflowing_literals
- patterns_in_fns_without_body
- pub_use_of_private_extern_crate
- soft_unstable
- unconditional_panic
- unknown_crate_types
- useless_deprecated
当您在代码中编写 literal 255+1
时,编译器会在编译时评估表达式并立即看到溢出,无论是在调试模式还是发布模式。当书中说 --release
禁用溢出保护时,它指的是运行时检查。你可以看到这段代码的不同之处:
fn increment (x: u8) -> u8 { x + 1 }
fn main() {
let x = 255;
println!("x: {},x+1: {}",x,increment (x));
}
如果您在调试模式下运行此代码,您将得到:
thread 'main' panicked at 'attempt to add with overflow',src/main.rs:1:30
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
但是如果你在发布模式下运行它,你会得到:
x: 255,x+1: 0