Rust —— 数据类型和函数

数据类型(Data Type)

Rust 是一门静态编译语言,必须在编译时知道所有变量的类型,所以声明时需要标注数据类型。

1. 标量类型(Scalar Type)

Rust 有四种主要标量类型:整数、浮点数、布尔值和字符。

1.1 整数类型(Integer)

Length Signed (有符号类型) Unsigned (无符号类型)
8-bit i8 (-128 to 127) u8 (0 to 255)
16-bit i16 (-32,768 to 32,767) u16 (0 to 65,535)
32-bit i32 (-2^31 to 2^31-1) u32 (0 to 2^32-1)
64-bit i64 (-2^63 to 2^63-1) u64 (0 to 2^64-1)
128-bit i128 (-2^127 to 2^127-1) u128 (0 to 2^128-1)
arch(依架构而定) isize usize
  • isizeusize 的大小取决于运行程序的计算机架构:
    • 64 位系统 → 64 位
    • 32 位系统 → 32 位

⚠️ 注意:如果声明变量的值超过数据类型的范围会导致 整数溢出(Integer Overflow)

1.2 浮点数类型(Floating-Point Type)

Rust 中浮点数类型有两种:f32f64。默认是 f64

在现代 CPU 上,f64 的速度和 f32 基本相同,但精度更高。

1
2
3
4
fn main() {
let x = 2.0; // f64
let y: f32 = 3.0; // f32
}

1.3 布尔类型(Boolean Type)

布尔值有两个可能的值:truefalse,大小为 1 个字节。

1
2
3
4
5
6
7
8
fn main() {
let t = true;
let f: bool = false; // 显式类型标注

if f {
println!("就这样吧");
}
}

1.4 字符类型(Char Type)

  • Rust 中用 '' 来指定 char 类型的字符
  • "" 来指定字符串 string
  • char 占用 4 个字节
1
2
3
4
5
fn main() {
let c = 'z';
let z: char = 'ℤ';
let heart_eyed_cat = '😻';
}

2. 复合类型(Compound Type)

Rust 有两种复合类型:元组(Tuple)数组(Array)

2.1 元组(Tuple Type)

  • 元组可以存放不同类型的值
  • 长度固定,声明后不可改变
1
2
3
fn main() {
let tup: (i32, f64, u8) = (500, 6.4, 1);
}

获取元组的值有两种方式:

  • 解构(Destructuring)

    1
    2
    3
    4
    5
    fn main() {
    let tup: (i32, f64, u8) = (500, 6.4, 1);
    let (x, y, z) = tup;
    println!("The value of x is: {x}");
    }
  • 索引(Index)

    1
    2
    3
    4
    5
    fn main() {
    let tup: (i32, f64, u8) = (500, 6.4, 1);
    let x = tup.0;
    println!("The value of x is: {x}");
    }

⚠️ 没有任何值的元组叫 unit 类型,写作 ()


2.2 数组(Array Type)

  • 所有元素必须是相同类型
  • 长度固定,存放在
1
2
3
fn main() {
let a = [1, 2, 3, 4, 5];
}

Rust 中的数组具有固定长度,这点与其它语言不同,其它编程语言中数组是可变长度,与 Rust 中的 vector 类似。当你想将数据分配在栈上而不是堆或者你想确保始终有固定数量的元素时,数组非常有用,比如一年的月数是固定的。

1
2
3
4
let months = [
"January", "February", "March", "April", "May", "June",
"July", "August", "September", "October", "November", "December"
];

指定数组类型与长度:

1
let a: [i32; 5] = [1, 2, 3, 4, 5];

指定初始值和长度:

1
let a = [3; 5]; // 等同于 [3, 3, 3, 3, 3]

数组是连续存放在栈上的有序结构,可以通过索引访问。Rust 的索引下标从 0 开始。

  • 访问数组元素

    1
    2
    3
    4
    5
    6
    fn main() {
    let a = [1, 2, 3, 4, 5];

    let first = a[0]; // 访问数组中第一个元素
    let second = a[1]; // 访问数组中第二个元素
    }
  • 数组下标越界

    如果下标不在 [0, Length-1] 范围内:

    • 编译阶段:直接报 panic 警告
    • 运行阶段:无法提前知道输入,越界时会 立即终止程序,而不是访问无效内存
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
use std::io;

fn main() {
let a = [1, 2, 3, 4, 5];

println!("Please enter an array index.");
let mut index = String::new();

io::stdin()
.read_line(&mut index)
.expect("Failed to read line");

let index: usize = index.trim().parse().expect("Index entered was not a number");

let element = a[index];
println!("The value of the element at index {index} is: {element}");
}

⚠️ Rust 的安全特性:遇到越界立刻退出,避免无效内存访问。


函数(Function)

函数由以下部分构成:

  • fn 关键字
  • 函数名 add
  • 参数 x, y 和参数类型 i32
  • 函数体 x + y
  • 返回值类型 i32
1
2
3
4
5
6
7
8
fn main() {
let x = add(1, 2);
println!("The value of x is: {x}");
}

fn add(x: i32, y: i32) -> i32 {
x + y
}

语句与表达式

  • 语句(Statements):执行操作,但不返回值

    1
    2
    3
    4
    5
    6
    fn main() {
    // ❌ 错误写法
    // 因为 let y = 6 是语句,没有返回值
    // 这是 Rust 的一个特性,如果是 C 或 Ruby,赋值操作会返回被赋的值 6
    let x = (let y = 6);
    }
  • 表达式(Expression):计算并返回值

    1
    2
    3
    4
    5
    6
    7
    8
    fn main() {
    let y = {
    let x = 3;
    x + 1 // 没有分号,表示表达式
    };

    println!("The value of y is: {y}");
    }

Hooray!数据类型和函数学习完成!!!