Rust从入门到精通之入门篇:4.变量与数据类型
变量与数据类型
学习目标
完成本章学习后,你将能够:
- 理解 Rust 中变量的声明和可变性概念
- 掌握变量遮蔽(shadowing)的使用方法
- 了解 Rust 的基本数据类型系统
- 使用不同的数值类型、布尔值和字符
- 创建和使用复合类型(元组和数组)
- 进行基本的类型转换
- 理解 Rust 中的字符串类型
在本章中,我们将学习 Rust 中的变量声明和基本数据类型。Rust 是一种静态类型语言,这意味着所有变量的类型在编译时必须是已知的,但 Rust 也提供了类型推断功能,使代码更加简洁。
变量声明
使用 let 关键字
在 Rust 中,使用 let
关键字声明变量:
let x = 5; // 声明一个变量 x 并赋值为 5
默认情况下,Rust 中的变量是不可变的(immutable)。这是 Rust 安全理念的一部分。
变量的可变性
如果需要一个可变变量,使用 mut
关键字:
let mut y = 5; // 声明一个可变变量
y = 10; // 可以修改它的值
尝试修改一个不可变变量会导致编译错误:
let x = 5;
x = 10; // 错误:不能对不可变变量二次赋值
变量遮蔽(Shadowing)
Rust 允许声明同名的新变量,新变量会遮蔽(shadow)之前的变量:
let x = 5;
let x = x + 1; // 创建一个新变量 x,值为 6
let x = x * 2; // 再次创建一个新变量 x,值为 12
遮蔽与 mut
的区别:
- 使用
let
创建的是一个新变量,可以改变类型 - 使用
mut
修改的是同一个变量,类型不能改变
let spaces = " "; // 字符串类型
let spaces = spaces.len(); // 数值类型,这是合法的
let mut spaces = " ";
spaces = spaces.len(); // 错误:类型不匹配
常量
使用 const
关键字声明常量:
const MAX_POINTS: u32 = 100_000;
常量与不可变变量的区别:
- 常量必须显式标注类型
- 常量可以在任何作用域中声明,包括全局作用域
- 常量只能设置为常量表达式,不能是函数调用的结果或运行时计算的值
- 常量在整个程序运行期间有效
数据类型
Rust 是静态类型语言,每个变量必须有一个确定的类型。大多数情况下,编译器可以推断类型,但有时需要显式标注。
标注类型
使用冒号 :
后跟类型名来标注变量类型:
let x: i32 = 5; // 显式指定 x 的类型为 32 位有符号整数
标量类型
Rust 有四种主要的标量类型:整数、浮点数、布尔值和字符。
整数类型
长度 | 有符号 | 无符号 |
---|---|---|
8位 | i8 | u8 |
16位 | i16 | u16 |
32位 | i32 | u32 |
64位 | i64 | u64 |
128位 | i128 | u128 |
架构相关 | isize | usize |
默认整数类型是 i32
。
整数字面值可以使用不同的表示方法:
let decimal = 98_222; // 十进制
let hex = 0xff; // 十六进制
let octal = 0o77; // 八进制
let binary = 0b1111_0000; // 二进制
let byte = b'A'; // 字节(仅限 u8)
可以使用下划线提高可读性:1_000_000
。
浮点数类型
Rust 有两种浮点数类型:f32
和 f64
。默认是 f64
。
let x = 2.0; // f64
let y: f32 = 3.0; // f32
数值运算
Rust 支持基本的数学运算:
// 加法
let sum = 5 + 10;
// 减法
let difference = 95.5 - 4.3;
// 乘法
let product = 4 * 30;
// 除法
let quotient = 56.7 / 32.2;
// 取余
let remainder = 43 % 5;
布尔类型
布尔类型 bool
有两个可能的值:true
和 false
。
let t = true;
let f: bool = false;
字符类型
char
类型表示单个 Unicode 字符,使用单引号表示。
let c = 'z';
let z = 'ℤ';
let heart_eyed_cat = '😻';
char
类型占用 4 字节,可以表示任何 Unicode 标量值。
复合类型
Rust 有两种基本的复合类型:元组(tuple)和数组(array)。
元组类型
元组是一个将多个不同类型的值组合到一起的复合类型。
let tup: (i32, f64, u8) = (500, 6.4, 1);
可以使用模式匹配来解构元组:
let tup = (500, 6.4, 1);
let (x, y, z) = tup;
println!("y 的值是: {}", y);
也可以使用索引访问元组元素:
let x: (i32, f64, u8) = (500, 6.4, 1);
let five_hundred = x.0;
let six_point_four = x.1;
let one = x.2;
数组类型
数组中的每个元素必须具有相同的类型,且数组长度是固定的。
let a = [1, 2, 3, 4, 5];
声明数组类型的语法:
let a: [i32; 5] = [1, 2, 3, 4, 5];
创建包含相同值的数组:
let a = [3; 5]; // 等同于 let a = [3, 3, 3, 3, 3];
访问数组元素:
let a = [1, 2, 3, 4, 5];
let first = a[0];
let second = a[1];
数组访问是边界检查的,访问超出数组范围的元素会导致运行时错误(panic)。
类型转换
显式类型转换
Rust 要求显式类型转换,使用 as
关键字:
let a = 5;
let b = 2.0;
let c = a as f64 + b; // 将 a 转换为 f64 类型
类型推断
Rust 编译器可以根据上下文推断变量类型:
let x = 5; // 推断为 i32
let y = 1.0; // 推断为 f64
字符串
Rust 中有两种主要的字符串类型:String
和 &str
。
字符串字面值
字符串字面值是不可变的,类型为 &str
:
let s = "hello";
String 类型
String
类型是可增长、可变、有所有权的字符串类型:
let mut s = String::from("hello");
s.push_str(", world!"); // 追加字符串
println!("{}", s); // 输出 "hello, world!"
示例程序
让我们编写一个程序,展示 Rust 中的变量和数据类型:
fn main() {
// 变量和可变性
let x = 5;
println!("x 的值是: {}", x);
let mut y = 5;
println!("y 的初始值是: {}", y);
y = 10;
println!("y 的新值是: {}", y);
// 变量遮蔽
let z = 1;
let z = z + 1;
let z = z * 2;
println!("z 的值是: {}", z);
// 常量
const MAX_POINTS: u32 = 100_000;
println!("常量值是: {}", MAX_POINTS);
// 数据类型
let a: i32 = -30;
let b: u32 = 30;
let c = 30; // 默认为 i32
println!("整数: {}, {}, {}", a, b, c);
let d = 2.5; // f64
let e: f32 = 3.0;
println!("浮点数: {}, {}", d, e);
let f = true;
let g: bool = false;
println!("布尔值: {}, {}", f, g);
let h = 'z';
let i = '😊';
println!("字符: {}, {}", h, i);
// 复合类型
let tup = (500, 6.4, true);
let (j, k, l) = tup;
println!("元组解构: {}, {}, {}", j, k, l);
println!("元组索引: {}, {}, {}", tup.0, tup.1, tup.2);
let arr = [1, 2, 3, 4, 5];
let first = arr[0];
let second = arr[1];
println!("数组元素: {}, {}", first, second);
// 字符串
let s1 = "hello";
let mut s2 = String::from("hello");
s2.push_str(", world!");
println!("字符串: {}, {}", s1, s2);
}
总结
在本章中,我们学习了:
- 使用
let
声明变量,默认不可变 - 使用
mut
创建可变变量 - 变量遮蔽的概念和用法
- 使用
const
声明常量 - Rust 的基本数据类型:整数、浮点数、布尔值和字符
- 复合类型:元组和数组
- 字符串类型:
&str
和String
- 类型转换和类型推断
理解变量和数据类型是学习任何编程语言的基础。Rust 的类型系统是其安全性和性能的重要保障,掌握这些基础知识将帮助你编写更加健壮的 Rust 程序。在下一章中,我们将学习 Rust 的控制流结构,这将使你能够编写更加复杂和有用的程序。