生于忧患,咸鱼安乐
Toggle navigation
Home
About Me
Archives
Tags
Rust Digest -- 变量、常量、数据类型
Rust
2021-04-07 19:45:08
312
0
0
squarefong
Rust
# 变量与可变性 ## 可变性 > 变量默认是不可改变的(immutable)。这是推动你以充分利用 Rust 提供的安全性和简单并发性来编写代码的众多方式之一。当变量不可变时,一旦值被绑定一个名称上,你就不能改变这个值。 ```rust fn main() { let x = 5; println!("The value of x is: {}", x); x = 6; println!("The value of x is: {}", x); } ``` 保存并使用 `cargo run` 运行程序。应该会看到一条错误信息,如下输出所示: ``` error[E0384]: cannot assign twice to immutable variable `x` --> src/main.rs:4:5 | 2 | let x = 5; | - first assignment to `x` 3 | println!("The value of x is: {}", x); 4 | x = 6; | ^^^^^ cannot assign twice to immutable variable ``` **也就是说,只写 let x = 5,效果相当于于C艹里面的const int x = 5;** **如果希望变量可变,则需要在变量名前加`mut`。** ``` fn main() { let mut x = 5; //加 mut 来使其可变了 println!("The value of x is: {}", x); x = 6; println!("The value of x is: {}", x); } ``` ## 常量 类似于不可变变量,常量是绑定到一个名称的不允许改变的值,不过常量与变量还是有一些区别: 1. 首先,不允许对常量使用 mut。 2. 声明常量使用 const 关键字(而不是 let),并且 ***必须*** 注明值的类型。 3. 常量可以在任何作用域中声明,包括全局作用域。在声明它的作用域之中,常量在整个程序生命周期中都有效。这在一个值需要被很多部分的代码用到时很有用。 4. 常量只能被设置为常量表达式,而不能是函数调用的结果,或任何其他只能在运行时计算出的值。 ## 隐藏(Shadowing) 我们可以定义一个与之前变量同名的新变量,而新变量会 **隐藏** 之前的变量。`mut` 与隐藏的区别是,当再次使用`let`时,实际上创建了一个新变量,我们可以改变值的类型,但复用这个名字。 ```rust let mut guess = String::from("hello"); println!("Addr of guess: {:X}", &guess as *const String as usize); let guess: u32 = match guess.trim().parse() { Ok(num) => num, Err(_) => {println!("invalid input");continue;}, }; println!("Addr of guess: {:X}", &guess as *const u32 as usize); ``` 执行获得的输出: ``` Addr of guess: 7FFC09F48920 Addr of guess: 7FFC09F489F4 ``` **新变量和旧变量仅仅只是名字相同,但是地址并不相同。** # 数据类型 Rust 是 **静态类型**(statically typed)语言,也就是说在编译时就必须知道所有变量的类型。根据值及其使用方式,编译器通常可以推断出我们想要用的类型。**但是,当多种类型均有可能时**,必须增加类型注解(比如使用 parse 将 String 转换为数字时): ```rust let guess: u32 = "42".parse().expect("Not a number!"); ``` 如果不添加类型注解,Rust 会显示如下错误,这说明编译器需要我们提供更多信息,来了解我们想要的类型: ``` error[E0282]: type annotations needed ``` 在 Rust 中,每一个值都属于某一个**数据类型(data type)**,这告诉 Rust 它被指定为何种数据,以便明确数据处理方式。我们将看到两类数据类型子集:**标量(scalar)和复合(compound)**。 ## 标量(scalar) 标量(scalar)类型代表一个单独的值。Rust 有**四种基本的标量类型:整型、浮点型、布尔类型和字符类型**。 ### 整型 **整数** 是一个没有小数部分的数字。 | 长度 | 有符号 | 无符号 | | :--- | :--- | :--- | | 8-bit | i8 | u8 | | 16-bit | i16 | u16 | | 32-bit | i32 | u32 | | 64-bit | i64 | u64 | | 128-bit | i128 | u128 | | arch | isize | usize | 每一个有符号的变体可以储存包含从 $[ - (2^{n - 1}) , 2^{n - 1} )$ 在内的数字,这里 n 是变体使用的位数。无符号的变体可以储存从 $[0, 2^{n - 1})$ 的数字。 所以 i8 可以储存从 $-(2^7)$ 到 $2^7 - 1$ 在内的数字, u8 可以储存从 0 到 $2^8 - 1$ 的数字 可以使用下面表格中的任何一种形式编写数字字面值。 | 数字字面值 | 例子 | | :-- | :-- | | Decimal (十进制) | 98_222 | | Hex (十六进制) | 0xff | | Octal (八进制) | 0o77 | | Binary (二进制) | 0b1111_0000 | | Byte (单字节字符)(仅限于u8) | b'A' | 注意, **除 byte 以外的所有数字字面值允许使用类型后缀**,例如 `57u8`,同时也允许使用 `_` 做为分隔符以方便读数,例如`1_000`。 ### 浮点型 Rust 也有两个原生的 浮点数(floating-point numbers)类型,它们是带小数点的数字。Rust 的浮点数类型是 `f32` 和 `f64`,分别占 32 位和 64 位。默认类型是 `f64`。 ### 布尔型 Rust 中的布尔类型有两个可能的值:true 和 false。Rust 中的布尔类型使用 bool 表示。 ### 字符类型 Rust 的 char 类型是语言中最原生的字母类型。(注意 char 由单引号指定,不同于字符串使用双引号。) ```rust fn main() { let c = 'z'; let z = 'ℤ'; let heart_eyed_cat = '😻'; } ``` Rust 的 **char 类型的大小为四个字节**(four bytes),并代表了一个 **Unicode 标量值**(Unicode Scalar Value),这意味着它可以比 ASCII 表示更多内容。 ## 复合类型 复合类型(Compound types)可以将多个值组合成一个类型。Rust 有两个**原生的复合类型**:**元组**(tuple)和**数组**(array)。 ### 元组类型 元组是一个将**多个类型**的值**组合进一个复合类型**的主要方式。元组**长度固定**:一旦声明,其长度不会增大或缩小。 可以使用包含在圆括号中的逗号分隔的值列表来创建一个元组。元组中的每一个位置都有一个类型,而且这些不同值的类型也不必是相同的。 ```rust let tup: (i32, f64, u8) = (500, 6.4, 1); //类型注解可以省略 ``` 元组是一个单独的复合元素,为了从元组中获取单个值,可以使用**模式匹配**(pattern matching)来**解构**(destructure)元组值,也可以使用点号(.)后跟值的索引来直接访问它们,像这样: ``` fn main() { let tup = (500, 6.4, 1); let (x, y, z) = tup; println!("The value of y is: {}", y); let five_hundred = tup.0; println!("The value of y is: {}", y); } ``` ### 数组类型 数组中的每个元素的类型必须相同,Rust 中的数组是固定长度的,一旦声明,它们的长度不能增长或缩小。 ```rust let a = [1, 2, 3, 4, 5]; //数组中的值位于中括号内的逗号分隔的列表中 ``` ``` let a: [i32; 5] = [1, 2, 3, 4, 5]; //i32 是每个元素的类型。分号之后,数字 5 表明该数组包含五个元素。 ``` ``` let a = [3; 5]; //为每个元素创建包含相同值的数组 //效果和let a = [3, 3, 3, 3, 3];相同 ``` 访问数组元素和别的语言一样,使用下标。 ```rust fn main() { let mut a = [1, 2, 3, 4, 5]; let first = a[0]; a[0] = 10; println!("{}, {}",first, a[0]); } ``` 显示输出为: `1, 10` 如果我们访问数组结尾之后的元素,可以编译通过,不过在运行时会因错误而退出。
Pre:
Rust Digest -- 所有权、引用、借用
Next:
Rust Digest -- Hello,World
0
likes
312
Weibo
Wechat
Tencent Weibo
QQ Zone
RenRen
Please enable JavaScript to view the
comments powered by Disqus.
comments powered by
Disqus
Table of content