常量
Rust 中的常量用关键字 const
定义,常量的值在编译时就确定了,不能在之后改变。常量要在定义的时候指定类型。
fn main(){
const x: i32 = 5;
println!("x = {}", x); // 输出:x = 5
}
变量与不可变性
Rust 中变量的类型分为两种:不可变变量(let
)和可变变量(let mut
)。
相同点:
- 变量都必须在声明时初始化。
- 变量的类型在编译时就确定了,不能在之后改变。
不同点:
let
:变量默认是不可变的,不能在之后重新赋值。(可重新绑定)let mut
:变量可以在之后重新赋值。
fn main(){
let x = 5;
let mut y = 5;
// x = 6; // 编译错误,不可变变量不能重新赋值
y = 6; // 可以重新赋值
let x = 10; // 可以重新绑定
println!("x = {}, y = {}", x, y); // 输出:x = 10, y = 6
}
由于 Rust 没有垃圾回收,变量在超出作用域后会被自动清理。变量默认不可变,等于是在提醒开发者,如果代码中给let
变量赋值了,编译器会直接报错(不可变的原因,有很多观点,这是其中一种观点)。
常量与不可变变量的区别
- 常量需要显示声明类型;变量有类型推导。
- 常量只能绑定到常量表达式,不能绑定到函数调用的返回值;而变量可以绑定到任何表达式。
- 常量可以在任意作用域中声明;而变量只能在其所在的作用域或更内层的作用域中声明。
- 常量不可重新绑定,变量可重新绑定。
const MAX_POINTS: u32 = 100_000;
fn main() {
let x = 5;
let x = x + 1; // 变量可以重新绑定
// const MAX_POINTS: u32 = 100; // 常量不能重新绑定
// MAX_POINTS = 100; // 常量不能重新绑定
println!("x = {}, MAX_POINTS = {}", x, MAX_POINTS); // 输出:x = 6, MAX_POINTS = 100_000
}
静态变量
静态变量(static variable)是指在整个程序运行期间都存在的变量,其值在程序开始时就被初始化,并且在程序结束时才被销毁。静态变量通常用于存储全局状态、常量或共享数据。静态变量的定义使用 static
关键字,其语法为static 变量名: 类型 = 初始值;
,不可省略类型定义。static
和const
基本一样,Rust 程序员基本上只使用const
。
static MAX_POINTS: u32 = 100_000;
fn main() {
println!("MAX_POINTS = {}", MAX_POINTS); // 输出:MAX_POINTS = 100000
}
数据类型
Rust 是静态类型语言,变量在编译时就必须知道其类型,在定义的时候不一定要指定类型,在使用变量的时候会根据上下文进行类型推导。Rust 中的数据类型分为两大类:标量(scalar)和复合(compound)。
标量(scalar)
标量(scalar)类型表示一个单独的值,类似Java中原生数据类型。Rust 有四种基本的标量类型:整型、浮点型、布尔型和字符型。
整型(integer):
整型(integer)是没有小数部分的数字,Rust 中的整型分为有符号整型(signed integer)和无符号整型(unsigned integer)。
位长度 | 有符号 | 无符号 |
---|---|---|
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 位架构将使用 32 位长度整型,如果是 64 位架构将使用 64 位长度整型。
整型支持以下几种进制表示方式:
进制 | 例子 |
---|---|
十进制 | 12_345 |
十六进制 | 0xF0 |
八进制 | 0o70 |
二进制 | 0b1111_0000 |
字节(等于 u8) | b'A' |
fn main() {
let x = 12_345; // 十进制
let y = 0xF0; // 十六进制
let z = 0o70; // 八进制
let a = 0b1111_0000; // 二进制
let b = b'A'; // 字节
println!("x = {}, y = {:o}, z = {:}, a = {:b}, b = {:?}", x, y, z, a, b);
// 输出:x = 12345, y = 360, z = 38, a = 11110000, b = 65
}
浮点型(floating-point):
浮点型(floating-point)是有小数部分的数字,Rust 中的浮点型分为两种:f32(单精度)和 f64(双精度),默认类型是 f64。
浮点数在计算机中是用二进制表示的,但是二进制无法表示所有的小数,所以浮点数的小数部分是不精确的。
fn main() {
let x = 2.0;
let y = 1.0 + 0.1 + 0.1;
println!("x = {}, y = {}", x, y); // 输出:x = 2.0, y = 1.2000000000000002
}
布尔型(boolean):
布尔型(boolean)只有两个值:true 和 false,用于表示逻辑值。
fn main() {
let x = true;
let y = false;
println!("x = {}, y = {}", x, y); // 输出:x = true, y = false
}
字符型(character):
字符型(character)是一个字符,Rust 中的字符类型是 char
,用单引号括起来。字符型表示一个 Unicode 标量值,包括字母、中日韩文、数字、标点符号、符号、emoji表情符号等。它占用 4 个字节,这意味着字符型的值可以存储在 32 位的整型中。由于有不同的编码会导致混乱,所以在 Rust 中字符串和字符都必须使用 UTF-8 编码,否则编译器会报错。
fn main() {
let x = 'A';
let y = '中';
let z = '🎉';
println!("x = {}, y = {}, z = {}", x, y, z); // 输出:x = A, y = 中, z = 🎉
}
复合(compound)
复合类型主要是元组和数组。
元组(tuple)
元组是一个可以包含各种类型值的组合,用 ( ) 包裹数据。
- 元组中的元素可以通过下标来访问,下标从 0 开始。
- 函数可以使用元组作为返回值,也可以使用元组作为参数。
- 元组可以使用解构(destructuring)来获取元组中的元素,解构可以使用模式匹配来实现。
- 元组可以使用
println
打印,但是太长的元组打印会报错。
fn reverse(pair: (i32, &str)) -> (&str, i32) {
// 解构元组
let (number, string) = pair;
return (string, number)
}
fn main(){
let x = (666, "Hello");
println!("x.0 = {}, x.1 = {}", x.0, x.1); // 输出:x.0 = 666, x.1 = Hello
let y = reverse(x);
println!("y = {:?}", y); // 输出:y = ("Hello", 666)
println!("y.0 = {}, y.1 = {}", y.0, y.1); // 输出:y.0 = Hello, y.1 = 666
}
数组(array)
数组是固定长度的有序列表,使用方括号 [ ] 包裹数据,元素之间用逗号分隔。
- 数组每个元素的类型必须相同。
- 数组的长度在编译时就必须确定,不能改变。
- 数组中的元素可以通过下标来访问,下标从 0 开始。
- 数组可以使用
println
打印,但是太长的数组打印会报错。 - 数组可以使用切片(slice)来获取数组中的一部分元素,切片是一个指向数组的指针,指向数组中的一段连续的元素,切片的类型是
&[T]
,其中 T 是数组元素的类型。
fn main() {
let x = [10, 20, 30];
println!("x = {:?}, len = {}", x, x.len()); // 输出:x = [10, 20, 30], len = 3
println!("x[0] = {}, x[2] = {}", x[0], x[2]); // 输出:x[0] = 10, x[2] = 30
let mut y:[i32; 5] = [100; 5]; // 可以初始化为一样的值
y[2] = 300;
println!("y = {:?}", y); // 输出:y = [100, 100, 300, 100, 100]
let z = &y[2..]; // 切片
println!("z = {:?}", z); // 输出:z = [300, 100, 100]
println!("z = {:?}", &y[2..4]); // 输出:z = [300, 100]
}