You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

204 lines
7.6 KiB

# 3
## Variables and Mutability
默认情况下,**变量是不可变的**。在没有使用mut的情况下,若重复修改变量的值会产生error[E0384]: cannot assign twice to immutable variable `x`
### Constants
同不可能变量相同,常量的值也不可修改。但是常量不允许使用mut,常量不仅在默认情况下是不可变的--**它们始终是不可变的的**。定义常量使用const关键字,而且必须在初始化时赋值,值只能是一个常量表达式。
```rust
const THREE_HOURS_IN_SECONDS: u32 = 60 * 60 * 3;
```
**Rust 的常量命名约定是全部使用大写字母,单词之间有下划线**
### Shadowing
声明一个同名新变量,覆盖先前的变量。
![image-20221228144724096](C:\Users\admin\AppData\Roaming\Typora\typora-user-images\image-20221228144724096.png)
![image-20221228144756450](C:\Users\admin\AppData\Roaming\Typora\typora-user-images\image-20221228144756450.png)
shadowing和使用mut存在两点不同,使用mut是不会改变变量类型,而使用let实际上是创建了一个同名新变量。且此变量可以不为之前的类型。
如下第一个spaces变量是字符串类型,第二个spaces变量是数字类型。使用let可以减少重新起名。但用mut无法做到这种事。
```
let spaces = " ";
let spaces = spaces.len();
```
运行时错误:mismatched types
```
let mut spaces = " ";
spaces = spaces.len();
```
## Data Types
rust 中每个值都有特定的数据类型。scalar and compound。
rust 是一种***静态类型***语言,因此它必须在编译时知道所有变量的类型。编译器通常会根据值和使用它的方式来推断值的类型。但在存在多种类型的情况下,需指明具体类型。例如数字类型。
```
let guess: u32 = "42".parse().expect("Not a number!");
```
### scalar
Scalar 用于表示单个值。rust中主要有四种类型:integers,floating-point numbers, Booleans, 以及characters。
#### integers
整数是没有小数部分的数字。i开头的为有符号的整数,u开头的为无符号的整数。
| Length | Signed | Unsigned |
| :------: | :----: | :------: |
| 8-bits | i8 | u8 |
| 16-bits | i16 | u16 |
| 32-bits | i32 | u32 |
| 64-bits | i64 | u64 |
| 128-bits | i128 | u128 |
| arch | isize | usize |
当需要表示有符号数的时候,需使用Signed,有符号数使用二进制补码来存储(原码取反+1)。二者的取值范围如下:
![image-20221228164640003](C:\Users\admin\AppData\Roaming\Typora\typora-user-images\image-20221228164640003.png)
| 进制 | 示例 |
| :--------------: | :---------: |
| Decimal | 98_222 |
| Hex | 0xff |
| Octal | 0o77 |
| Binary | 0b1111_0000 |
| Byte (`u8` only) | b'A' |
![image-20221228170044008](C:\Users\admin\AppData\Roaming\Typora\typora-user-images\image-20221228170044008.png)
注:数字间可以使用**_**为视觉分隔符。1_000的值等同于1000。
![image-20221229085022060](C:\Users\admin\AppData\Roaming\Typora\typora-user-images\image-20221229085022060.png)
##### overflow
![image-20221229090856434](C:\Users\admin\AppData\Roaming\Typora\typora-user-images\image-20221229090856434.png)
当使用u8类型时,值的范围为0-255,若将值赋为256,不管release还是debug都会报错 literal out of range for `u8 `
![image-20221229100932401](C:\Users\admin\AppData\Roaming\Typora\typora-user-images\image-20221229100932401.png)
但是要是换成此种写法,在debug mode下会产生不变,而在 release mode下,不会检查整数溢出,若发生溢出,Rust执行二进制补码进行包装,当值为u8类型时,256会变成0,257会变成1。程序不会panic,但是值可能不是期望值。
处理显式溢出,可以使用标准库的以下方法 [rust doc](https://doc.rust-lang.org/std/primitive.i32.html#method.overflowing_add):
1. wrapping_add 当overflow时,会自动回到最小值,结果和使用release相同,但是使用Wrapping包装类可以在debug模式下使用,同时避免出现不可预期的结果。
![image-20221229103713797](C:\Users\admin\AppData\Roaming\Typora\typora-user-images\image-20221229103713797.png)
2. 使用checked_add方法。会在溢出时返回None,方便定位是否产生溢出。
![image-20221229111802596](C:\Users\admin\AppData\Roaming\Typora\typora-user-images\image-20221229111802596.png)
3,使用overflowing_add。此方法会返回一个结果和一个布尔值来定位是否溢出,相较于wrapping_add多一个是否溢出的标记。
![image-20221229112810102](C:\Users\admin\AppData\Roaming\Typora\typora-user-images\image-20221229112810102.png)
4. 使用saturating_add。越界时数值为临界点的值。
![image-20221229113501276](C:\Users\admin\AppData\Roaming\Typora\typora-user-images\image-20221229113501276.png)
#### Floating-Point Types
浮点数是带小数点的数字。Rust有f32和f64两种。浮点数都是有符号数,且默认为f64。
```
fn main() {
let x = 2.0; // f64
let y: f32 = 3.0; // f32
}
```
#### Numeric Operations
rust数字类型支持所有基本数学运算,整数除法时,结果取最接近0的整数。
![image-20221229160910795](C:\Users\admin\AppData\Roaming\Typora\typora-user-images\image-20221229160910795.png)
#### The Boolean Type
布尔类型一个字节,有true和false两种值。可以隐式和显式声明。
```
fn main() {
let t = true;
let f: bool = false; // with explicit type annotation
}
```
#### The Character Type
char是rust最原始的类型。 字符型使用单引号指定文字,而非双引号。同时大小为4个字节,表示一个Unicode标量值,故而字符型不仅可以表示ASCII,也可以表示带音调的字母、中文、日文、韩文字符、emoji以及零宽空格。
Unicode标量值的范围 U+0000 到 U+D7FF 和 U+E000 到 U+10FFFF(含)。字符于rust中比较特殊。
![image-20221229162843669](C:\Users\admin\AppData\Roaming\Typora\typora-user-images\image-20221229162843669.png)
### compound Types
复合类型可以将多个值组合成一个类型。rust中有两种基本的符合类型:元组(tuples)和数组(arrays)。
#### The Tuple Type
元组是将多个具有多种类型的值组合成一个复合类型的通用方法。固定长度:声明后,它们的大小就不能增加或缩小。若要从元组中取单个值:1.通过模式匹配来解析元组值。 2.通过使用句点(.)后接索引来访问元素(从0开始)。
![image-20221229170443559](C:\Users\admin\AppData\Roaming\Typora\typora-user-images\image-20221229170443559.png)
当一个元组没有任何值,那么它拥有一个特殊的名字-> unit。 这个值及其对应的类型都写作(),表示空值或空返回类型。一般用于函数无返回值时。
```rust
fn say_hi() -> () {
println!("Hi!");
}
// 显式返回
fn say_hi() -> () {
println!("Hi!");
return ();
}
```
#### The Array Type
数组每个元素必须具有相同的类型,Rust中数组具有固定长度。数组中的值在方括号内以逗号分隔。故而当数量固定时数组很有用。vector相较于数组更灵活,可以扩大或缩小大小。
![image-20221229173612760](C:\Users\admin\AppData\Roaming\Typora\typora-user-images\image-20221229173612760.png)
![image-20221229173829051](C:\Users\admin\AppData\Roaming\Typora\typora-user-images\image-20221229173829051.png)