基本语法
本章将介绍 Rust 的基本语法,包括变量、数据类型、函数和注释。这些是学习任何编程语言的基础。
变量与可变性
Section titled “变量与可变性”不可变变量(默认)
Section titled “不可变变量(默认)”在 Rust 中,变量默认是不可变的(immutable):
fn main() { let x = 5; println!("x 的值是: {}", x);
// 下面这行会报错! // x = 6; // error: cannot assign twice to immutable variable}这是 Rust 保证安全性的重要特性之一。
如果需要修改变量,使用 mut 关键字:
fn main() { let mut x = 5; println!("x 的值是: {}", x);
x = 6; // 现在可以修改了 println!("x 的值是: {}", x);}变量遮蔽(Shadowing)
Section titled “变量遮蔽(Shadowing)”可以用相同的名字声明新变量,新变量会”遮蔽”旧变量:
fn main() { let x = 5; let x = x + 1; // 遮蔽,创建新变量 let x = x * 2; // 再次遮蔽
println!("x 的值是: {}", x); // 输出: 12}遮蔽与 mut 的区别:
- 遮蔽创建新变量,可以改变类型
mut只能修改值,不能改变类型
// 遮蔽可以改变类型let spaces = " "; // &str 类型let spaces = spaces.len(); // usize 类型,合法
// mut 不能改变类型let mut spaces = " ";// spaces = spaces.len(); // 错误!类型不匹配常量使用 const 声明,必须标注类型,且必须是编译时常量:
const MAX_POINTS: u32 = 100_000;const PI: f64 = 3.14159265358979;常量与不可变变量的区别:
- 常量必须标注类型
- 常量必须是编译时可确定的值
- 常量可以在任何作用域声明,包括全局
- 常量命名约定:全大写,下划线分隔
Rust 是静态类型语言,编译时必须知道所有变量的类型。
| 长度 | 有符号 | 无符号 |
|---|---|---|
| 8-bit | i8 | u8 |
| 16-bit | i16 | u16 |
| 32-bit | i32 | u32 |
| 64-bit | i64 | u64 |
| 128-bit | i128 | u128 |
| arch | isize | usize |
isize 和 usize 的大小取决于运行程序的计算机架构(32位或64位)。
fn main() { let a: i32 = 42; let b: u8 = 255; let c = 98_222; // 可以用下划线增加可读性 let d = 0xff; // 十六进制 let e = 0o77; // 八进制 let f = 0b1111_0000; // 二进制 let g = b'A'; // 字节(仅限 u8)}fn main() { let x = 2.0; // f64(默认) let y: f32 = 3.0; // f32}fn main() { let t = true; let f: bool = false;}Rust 的 char 是 4 字节的 Unicode 标量值:
fn main() { let c = 'z'; let z = 'ℤ'; let heart_eyed_cat = '😻';
println!("字符大小: {} 字节", std::mem::size_of::<char>()); // 4}元组(Tuple)
Section titled “元组(Tuple)”元组可以包含不同类型的值,长度固定:
fn main() { // 创建元组 let tup: (i32, f64, u8) = (500, 6.4, 1);
// 解构 let (x, y, z) = tup; println!("y 的值是: {}", y);
// 索引访问(从 0 开始) let five_hundred = tup.0; let six_point_four = tup.1; let one = tup.2;}空元组 () 称为”单元类型”,表示空值或空返回类型。
数组(Array)
Section titled “数组(Array)”数组的所有元素必须是相同类型,长度固定:
fn main() { // 创建数组 let a = [1, 2, 3, 4, 5]; let b: [i32; 5] = [1, 2, 3, 4, 5]; // 显式类型标注 let c = [3; 5]; // [3, 3, 3, 3, 3],5 个 3
// 访问元素 let first = a[0]; let second = a[1];
// 数组长度 println!("数组长度: {}", a.len());}注意:访问越界会导致运行时 panic:
fn main() { let a = [1, 2, 3]; // let element = a[10]; // 运行时 panic!}fn main() { println!("Hello from main!"); another_function();}
fn another_function() { println!("Hello from another function!");}Rust 不关心函数定义的顺序。
fn main() { print_value(5); print_labeled_value(5, 'h');}
fn print_value(x: i32) { println!("x 的值是: {}", x);}
fn print_labeled_value(value: i32, unit: char) { println!("值是: {}{}", value, unit);}注意:函数参数必须声明类型。
使用 -> 声明返回类型,最后一个表达式的值作为返回值:
fn five() -> i32 { 5 // 注意:没有分号,这是表达式}
fn plus_one(x: i32) -> i32 { x + 1}
fn main() { let x = five(); let y = plus_one(5); println!("x = {}, y = {}", x, y);}也可以使用 return 提前返回:
fn abs(x: i32) -> i32 { if x < 0 { return -x; } x}语句与表达式
Section titled “语句与表达式”- 语句(Statement):执行动作,不返回值
- 表达式(Expression):计算并产生值
fn main() { // 语句 let x = 5; // let 语句不返回值
// 表达式 let y = { let x = 3; x + 1 // 注意没有分号,这是表达式 };
println!("y = {}", y); // 输出: 4}重要:加上分号就变成了语句,不返回值:
fn main() { let y = { let x = 3; x + 1; // 加了分号,变成语句,返回 () }; // y 的类型是 (),不是 i32}// 这是单行注释
/* * 这是多行注释 * 可以跨越多行 */文档注释用于生成 API 文档:
/// 计算两个数的和////// # 参数////// * `a` - 第一个数/// * `b` - 第二个数////// # 示例////// ```/// let result = add(2, 3);/// assert_eq!(result, 5);/// ```fn add(a: i32, b: i32) -> i32 { a + b}运行 cargo doc --open 可以生成并查看文档。
练习 1:理解不可变性
Section titled “练习 1:理解不可变性”尝试编译以下代码,观察错误信息:
fn main() { let x = 5; x = 6; println!("{}", x);}修复它,使程序能够正常运行。
练习 2:编写加法函数
Section titled “练习 2:编写加法函数”编写一个函数 add,接收两个 i32 参数,返回它们的和:
fn add(a: i32, b: i32) -> i32 { // 你的代码}
fn main() { let result = add(3, 5); println!("3 + 5 = {}", result);}练习 3:元组解构
Section titled “练习 3:元组解构”创建一个元组存储一个人的信息:姓名(String)、年龄(u8)、身高(f32),然后解构并打印:
fn main() { let person = (String::from("张三"), 25, 175.5); // 解构并打印}练习 4:计算平均值
Section titled “练习 4:计算平均值”创建一个长度为 5 的整数数组,编写代码计算所有元素的平均值:
fn main() { let numbers = [10, 20, 30, 40, 50]; // 计算并打印平均值}提示:注意整数除法和浮点数除法的区别。
掌握了基本语法后,下一章我们将学习 Rust 的控制流:条件判断和循环。