Rust基础

第2课:变量与类型

🎯 本课目标

掌握Rust变量声明、可变性、遮蔽、常量,以及所有基本数据类型和类型转换。

1. 变量声明

1.1 let绑定

fn main() {
    let x = 5;           // 不可变绑定
    // x = 6;           // ❌ 编译错误!

    let mut y = 10;     // 可变绑定
    y = 20;               // ✅ OK
    println!("x = {}, y = {}", x, y);
}

✅ 编译验证通过

🔑 为什么默认不可变?

函数式理念:不可变数据更安全、易推理。90%的变量不需要修改。Rust让你显式选择可变性。

1.2 变量遮蔽(Shadowing)

fn main() {
    let x = 5;
    let x = x + 1;      // 新x = 6
    let x = x * 2;      // 新x = 12

    // 遮蔽可以改变类型!
    let spaces = "   ";        // &str
    let spaces = spaces.len();   // usize

    // mut不能改变类型
    // let mut n = 5;
    // n = "hello";  // ❌ 类型不匹配
    println!("x = {}, spaces = {}", x, spaces);
}

✅ 编译验证通过

1.3 常量

const MAX_POINTS: u32 = 100_000;
const PI: f64 = 3.14159265358979;

fn main() {
    println!("最大分数: {}", MAX_POINTS);
}

✅ 编译验证通过

特性letlet mutconst
可变性不可变可变不可变
类型标注可推断可推断必须标注
求值时机运行时运行时编译期
遮蔽允许允许不允许

2. 整数类型

类型位数范围
i88-128 ~ 127
u880 ~ 255
i3232-2³¹ ~ 2³¹-1
u64640 ~ 2⁶⁴-1
isize指针宽取决于平台
usize指针宽取决于平台
fn main() {
    let a: i32 = 42;
    let b: u8 = 255;
    let c = 98_222;          // i32
    let d = 0xff;            // 十六进制
    let e = 0o77;            // 八进制
    let f = 0b1111_0000;     // 二进制
    let g = b'A';            // 字节(u8)
}

✅ 编译验证通过

3. 浮点、布尔、字符

fn main() {
    let x: f32 = 3.14;       // 单精度
    let y: f64 = 2.71828;    // 双精度(默认)

    let t: bool = true;
    let c = '🦀';      // char是4字节Unicode

    // ⚠️ 浮点比较
    let a: f64 = 0.1 + 0.2;
    println!("0.1+0.2 = {:.17}", a); // 0.30000000000000004
}

✅ 编译验证通过

4. 复合类型

fn main() {
    // 元组
    let tup: (i32, f64, bool) = (500, 6.4, true);
    let (x, y, z) = tup;    // 解构
    println!("第一个: {}", tup.0);  // 索引

    // 数组
    let arr: [i32; 5] = [1, 2, 3, 4, 5];
    let zeros = [0; 100];       // 100个0
    let slice = &arr[1..3];   // 切片 [2,3]
}

✅ 编译验证通过

5. 类型转换

fn main() {
    let a: i32 = 42;
    let b: i64 = a as i64;         // 扩展:安全
    let c: u8 = a as u8;          // 截断:42
    let e: i8 = 300 as i8;       // 溢出:44

    // 安全转换
    use std::convert::TryInto;
    let big: i64 = 1_000_000;
    match big.try_into::<i32>() {
        Ok(n) => println!("转换成功: {}", n),
        Err(_) => println!("溢出"),
    }
}

✅ 编译验证通过

6. 内存布局

栈内存布局(64位系统): 0x7ffc00 │ x: 5 │ i32, 4 bytes 0x7ffc04 │ y: true │ bool, 1 byte + 3 padding 0x7ffc08 │ tup.0: 500 │ tuple i32 0x7ffc0c │ tup.1: 6.4 │ tuple f64 (8 bytes) 0x7ffc14 │ tup.2: true │ tuple bool 0x7ffc18 │ arr[0..4] │ [i32;5] = 20 bytes 0x7ffc2c │ arr[4] │ 所有栈变量编译期确定大小,连续排列

📝 练习题

练习1:类型计算

计算各类型大小并验证:

println!("i32: {}", std::mem::size_of::<i32>());
println!("(i32,f64,bool): {}", std::mem::size_of::<(i32,f64,bool)>());

练习2:遮蔽vs可变

let mut s = "hello";
s = "world";   // 合法吗?
let n = 5;
let n = "five";  // 合法吗?

练习3:整数溢出

let max: u8 = 255;
let wrapped = max.wrapping_add(1);  // 0
let sat = max.saturating_add(1);   // 255
🏆

成就解锁:类型大师

掌握Rust所有基本类型和类型系统基础


📚 扩展阅读

以下资源帮助你深入学习本课主题:

🔑 关键术语回顾

本课涉及的核心概念,确保你理解每一个:

术语说明
所有权Rust内存管理的核心机制,每个值有唯一所有者
借用通过引用访问数据,不获取所有权
生命周期引用有效的范围,编译期分析工具
traitRust的接口/抽象机制,类似其他语言的接口
泛型参数化类型,零成本抽象
模式匹配强大的数据解构和分支机制
零成本抽象高层抽象不引入运行时开销
fearless concurrency编译器保证线程安全

💬 学习建议

  1. 动手编码 — 每个代码示例都在本地运行一遍
  2. 修改实验 — 故意改错代码,看编译器报什么错
  3. 完成练习 — 每课的练习题是巩固知识的关键
  4. 阅读源码 — 看标准库和优秀开源项目的实现
  5. 写项目 — 真正掌握需要构建真实项目

🤔 常见问题

Q: Rust学习曲线真的很陡吗?

A: 前期确实需要适应所有权和借用检查器,但一旦理解了,这些概念会让你的代码更可靠。大多数人2-4周就能上手。

Q: Rust适合什么项目?

A: 系统编程、Web服务、CLI工具、嵌入式、WASM、网络服务、数据库等。基本上需要性能和安全的地方都适合。

Q: 遇到编译错误怎么办?

A: Rust编译器的错误信息非常友好!仔细阅读,通常会指出问题所在和修复建议。也可以用cargo clippy获取更多提示。