3.1 Variables and Mutability

let x = 5; immutable
let mut x = 5; mutable

Constants

const THREE_HOURS_IN_SECONDS: u32 = 60 * 60 * 3;

You declare constants using the const keyword instead of the let keyword, and the type of the value must be annotated.

note= const 还能不能被 Shadowing 呢?
as the showing in the picture, const can not be shadowing

|475

Shadowing

遮蔽

fn main() {
    let x = 5;
 
    let x = x + 1;
 
    {
        let x = x * 2;
        println!("The value of x in the inner scope is: {x}");
    }
 
    println!("The value of x is: {x}");
}
cargo run
   Compiling variables v0.1.0 (file:///projects/variables)
    Finished dev [unoptimized + debuginfo] target(s) in 0.31s
     Running `target/debug/variables`
The value of x in the inner scope is: 12
The value of x is: 6

Data Types

scalar:标量
compound:复合

Scalar Types

Rust has four primary scalar types: integers, floating-point numbers, Booleans, and characters.

integers

LengthSignedUnsigned
8-biti8u8
16-biti16u16
32-biti32u32
64-biti64u64
128-biti128u128
archisizeusize

Additionally, the isize and usize types depend on the architecture of the computer your program is running on, which is denoted in the table as “arch”: 64 bits if you’re on a 64-bit architecture and 32 bits if you’re on a 32-bit architecture.

Note that number literals that can be multiple numeric types allow a type suffix, such as 57u8, to designate the type.

Number literalsExample
Decimal98_222
Hex0xff
Octal0o77
Binary0b1111_0000
Byte (u8 only)b’A’

Info

Integer Overflow

Let’s say you have a variable of type u8 that can hold values between 0 and 255. If you try to change the variable to a value outside that range, such as 256, integer overflow will occur, which can result in one of two behaviors. When you’re compiling in debug mode, Rust includes checks for integer overflow that cause your program to panic at runtime if this behavior occurs. Rust uses the term panicking when a program exits with an error; we’ll discuss panics in more depth in the “Unrecoverable Errors with panic! section in Chapter 9.

When you’re compiling in release mode with the --release flag, Rust does not include checks for integer overflow that cause panics. Instead, if overflow occurs, Rust performs two’s complement wrapping. In short, values greater than the maximum value the type can hold “wrap around” to the minimum of the values the type can hold. In the case of a u8, the value 256 becomes 0, the value 257 becomes 1, and so on. The program won’t panic, but the variable will have a value that probably isn’t what you were expecting it to have. Relying on integer overflow’s wrapping behavior is considered an error.

To explicitly handle the possibility of overflow, you can use these families of methods provided by the standard library for primitive numeric types:

  • Wrap in all modes with the wrapping_* methods, such as wrapping_add.
  • Return the None value if there is overflow with the checked_* methods.
  • Return the value and a boolean indicating whether there was overflow with the overflowing_* methods.
  • Saturate at the value’s minimum or maximum values with the saturating_*

Numeric Operations

Rust supports the basic mathematical operations you’d expect for all the number types: addition, subtraction, multiplication, division, and remainder. Integer division truncates toward zero to the nearest integer. The following code shows how you’d use each numeric operation in a let statement:

fn main() {
    // addition
    let sum = 5 + 10;
 
    // subtraction
    let difference = 95.5 - 4.3;
 
    // multiplication
    let product = 4 * 30;
 
    // division
    let quotient = 56.7 / 32.2;
    let truncated = -5 / 3; // Results in -1
 
    // remainder
    let remainder = 43 % 5;
}