入坑第一天
基础概念
每一个Rust程序都会用到的基础知识:变量、基本类型、函数、注释和控制流.
一、变量与常量
变量和可变性
变量默认是不可改变的
当变量不可改变时,一旦值被绑定一个名称上,就不能改变这个值 文件名:src/main.rs
fn main() {
let x = 5;
println!("The value of x is: {x}");
x = 6;
println!("The value of x is: {x}");
}
可变性也是非常有用的,可以用来更方便地编写代码。尽管变量默认是不可变的,你仍然可以在变量名前添加 mut 来使其可变。
fn main() {
let mut x = 5;
println!("The value of x is: {x}");
x = 6;
println!("The value of x is: {x}");
}
常量
类似不可变变量,常量 是绑定到一个名称的不允许改变的值。且不允许对常量使用常量,声明常量使用const关键字而不是let,并且必须注明值的类型。
常量只能被设置为常量表达式,而不可以是其他任何只能在运行时计算出的值。
Rust 对常量的命名约定是在单词之间使用全大写加下划线。 栗子:
const THREE_HOURS_IN_SECONDS: u32 = 60 * 60 * 3;
隐藏
我们可以定义一个与之前变量同名的新变量。此时第一个变量就被第二个变量隐藏(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
mut与隐藏的区别,当尝试对变量重新赋值时,若没有使用let关键字,就会导致编译时错误。
mut 与隐藏的另一个区别是,当再次使用 let 时,实际上创建了一个新变量,我们可以改变值的类型,并且复用这个名字。
二、数据类型
Rust是静态类型语言。必须在编译时知道所有变量的类型。
数据类型子集:标量 和 复合
标量类型
标量类型代表一个单独的值。Rust有四种基本的标量类型:整型、浮点型、布尔类型和字符类型。
整型
整数 是一个没有小数部分的数字。我们在第二章使用过 u32 整数类型。该类型声明表明,它关联的值应该是一个占据 32 比特位的无符号整数(有符号整数类型以 i 开头而不是 u)。下面表格展示了 Rust 内建的整数类型。我们可以使用其中的任一个来声明一个整数值的类型。有符号 和 无符号 代表数字能否为负值。
| 长度 | 有符号 | 无符号 |
|---|---|---|
| 8-bit | i8 | u8 |
| 16-bit | i16 | u16 |
| 32-bit | i32 | u32 |
| 64-bit | i64 | u64 |
| 128-bit | i128 | u128 |
| arch | isize | usize |
如u8可以存放0到255的值,如果修改为256会发生整型溢出的问题。
浮点型
Rust 也有两个原生的 浮点数(floating-point numbers)类型,它们是带小数点的数字。Rust 的浮点数类型是 f32 和 f64,分别占 32 位和 64 位。默认类型是 f64。所有的浮点型都是有符号的。 f32 是单精度浮点数,f64 是双精度浮点数。
fn main() {
let x = 2.0; // f64
let y: f32 = 3.0; // f32
}
布尔值
Rust 中的布尔类型有两个可能的值:true 和 false。Rust 中的布尔类型使用 bool 表示
fn main() {
let t = true;
let f: bool = false; // with explicit type annotation
}
字符类型
Rust 的 char 类型是语言中最原生的字母类型。
我们用单引号声明 char 字面量,而与之相反的是,使用双引号声明字符串字面量。
Rust 的 char 类型的大小为四个字节
fn main() {
let c = 'z';
let z: char = 'ℤ'; // with explicit type annotation
let heart_eyed_cat = '😻';
}
复合类型
复合类型(Compound types)可以将多个值组合成一个类型。Rust 有两个原生的复合类型:元组(tuple)和数组(array)。
元组类型
元组是一个将多个其他类型的值组合进一个复合类型的主要方式。
元组类型特点:
- 长度固定,一旦声明,其长度不会增大或缩小
- 使用包含在圆括号中的逗号分隔的值列表来创建一个元组。元组中的每一个位置都有一个类型,而且这些不同值的类型也不必是相同的。
fn main() {
let tup: (i32, f64, u8) = (500, 6.4, 1);
}
使用方式:
- 模式匹配: 使用点号(
.)后跟值的索引来直接访问它们。元组的第一个索引值是0,一次累加 - 解构
结构
fn main() {
let tup = (500, 6.4, 1);
let (x, y, z) = tup;
println!("The value of y is: {y}");
}
模式匹配
fn main() {
let x: (i32, f64, u8) = (500, 6.4, 1);
let five_hundred = x.0;
let six_point_four = x.1;
let one = x.2;
}
不带任何值的元组有个特殊的名称,叫做 单元(unit) 元组。这种值以及对应的类型都写作 (),表示空值或空的返回类型。如果表达式不返回任何其他值,则会隐式返回单元值。
数组类型
数组与元组不同,数组中的每个元素的类型必须相同。且数组长度固定。
定义:在方括号中包含每个元素的类型,后跟分号,再后跟数组元素的数量
访问:数组是可以在栈 (stack) 上分配的已知固定大小的单个内存块。可以使用索引来访问数组的元素。超过索引值是无效访问。
fn main() {
let a = [1, 2, 3, 4, 5];
let b: [i32; 5] = [1, 2, 3, 4, 5]; // 表示 i32是每个元素的类型,数字5表hi是包含5个元素。
let c = [3; 5]; // 表示元素的值等于3,且5个元素的值都是3.
}