当前位置: 首页 > news >正文

趣味学Rust基础篇(数据类型)

作为一个名长期从事编码工作的码农,我一直觉得编写程序就想玩乐高一样,想象一下,你要用乐高积木搭建一个复杂的模型。每一块积木都有不同的形状和功能:有小小的 1x1 方块(基础积木),也有能组合多个小块的复杂组件(组合积木)。在 Rust 世界里,数据类型就是这些“积木”。我们要学习的,就是认识这些积木(数据类型),并用它们构建出强大的程序。

Rust 是一个静态类型语言,这就意味着它像一个非常严格的建筑师,必须在“开工”(编译)之前就搞清楚每一块积木的型号。不过,Rust 很聪明,很多时候它能根据你放进去的“零件”(值)自动猜出积木型号。

积木的两大类:标量(单一积木)和复合(组合积木)

Rust 的积木主要分两大类:

  1. 标量类型 (Scalar):代表一个独立的值,就像一个 1x1 的小方块。
  2. ** 复合类型 **(Compound):能把多个值组合在一起,就像一个能连接多个小方块的大组件。

第一类:标量积木(单一值)

标量积木有四种基本款:整数、浮点数、布尔值、字符

1. 整数积木(i32, u8, isize…)

整数就是没有小数点的数字,比如 42, -100

  • 有符号 vs 无符号

    • i 开头的(如 i32):有符号(signed),能存正数、负数和零。i 代表 “integer”。
    • u 开头的(如 u8):无符号(unsigned),只能存零和正数。u 代表 “unsigned”。
  • 位数:后面的数字(如 32)代表这块积木的大小(位数),决定了它能存多大的数字。

    • i8:8位,范围是 -128 到 127。
    • u8:8位,范围是 0 到 255。
    • i32:32位,范围巨大,从 -2,147,483,648 到 2,147,483,647。

举例说明

let age: u8 = 25; // 年龄不可能是负数,用 u8 足够了
let temperature: i32 = -10; // 温度可以是零下,用 i32
let default_int = 42; // 不写类型,Rust 默认是 i32
  • isizeusize:这两个比较特殊,它们的大小取决于你的电脑是 32 位还是 64 位。它们通常用于数组索引内存地址

整数溢出:我们可以想象一个 u8 盒子(最大装 255),你非要塞进去 256。

  • Debug 模式(开发时):Rust 会立刻大喊“Panic!”(崩溃),提醒你出错了。
  • Release 模式(发布时):为了性能,Rust 会默默让它“回绕”:256 变成 0,257 变成 1… 这通常不是你想要的!

安全处理溢出:Rust 提供了专门的“安全工具”:

let max_u8: u8 = 255;
let result = max_u8.checked_add(1); // 检查加法是否会溢出
match result {Some(value) => println!("结果是 {value}"),None => println!("加法溢出啦!"),
}
  • 整数写法:Rust 支持多种写法,还允许用 _ 当“千分位”分隔符,超贴心!
    let decimal = 98_222;     // 十进制,就是 98222
    let hex = 0xff;           // 十六进制,255
    let octal = 0o77;         // 八进制,63
    let binary = 0b1111_0000; // 二进制,240
    let byte = b'A';          // 字节 (u8),65 (ASCII 'A')
    
2. 浮点数积木(f32, f64

浮点数就是带小数点的数字,比如 3.14, -0.001

  • f32:32位,单精度。
  • f64:64位,双精度。默认类型是 f64,因为现代 CPU 上它和 f32 差不多快,但精度更高。

例子

let pi = 3.1415926; // 不写类型,Rust 默认是 f64
let small_number: f32 = 1e-3; // 科学计数法,0.001

数学运算

fn main() {let sum = 5 + 10;        // 加法: 15let diff = 95.5 - 4.3;   // 减法: 91.2let prod = 4 * 30;       // 乘法: 120let quot = 56.7 / 32.2;  // 除法: 约 1.76let trunc = -5 / 3;      // 整数除法向零截断: -1 (不是 -1.666...)let rem = 43 % 5;        // 求余: 3println!("trunc = {trunc}, rem = {rem}");
}
3. 布尔积木(bool

最简单的积木,只有两个状态:true(真)和 false(假)。大小是 1 个字节。

例子

let is_raining = true;
let is_sunny: bool = false; // 显式类型注解
let comparison = 10 > 5;    // 比较表达式返回 bool: true

布尔值主要用于 if 条件判断。

4. 字符积木(char

char 是 Rust 中最基础的“字母”类型。注意:它和字符串 String 不一样!

  • 单引号 ' ' 包裹。
  • 大小是 4 个字节,可以表示Unicode 标量值,所以不仅能表示英文、数字,还能表示中文、日文、表情符号(emoji)等!

例子

let letter = 'z';
let number = '7';
let heart = '❤';
let cat = '😻';
let chinese = '中';
let math_symbol = 'ℤ'; // 整数集符号

重要提示:一个 char 不一定对应人类认知的一个“字符”。例如,一个带重音符号的字母 é 可能由多个 Unicode 码位组成。对于文本,通常使用 String 类型。


第二类:复合积木(组合值)

复合类型能把多个标量积木组合成一个更复杂的组件。

1. 元组积木(tuple

元组就像一个异构的、固定大小的盒子,可以装不同类型的东西。

  • 用小括号 ( ) 创建。
  • 一旦创建,大小不能改变。
  • 里面的元素可以是不同类型。

例子

// 创建一个元组,包含整数、浮点数和字符
let tup: (i32, f64, char) = (500, 6.4, 'z'); // 可以加类型注解// 创建元组(不加类型注解,Rust也能推断)
let tup = (500, 6.4, 'z');// 方法一:解构(Destructuring) - 把大盒子拆成小盒子
let (x, y, z) = tup; // x=500, y=6.4, z='z'
println!("y 的值是:{y}");// 方法二:通过索引访问 - 直接从大盒子里拿东西
let x = tup.0; // 第一个元素 (索引从0开始)
let y = tup.1; // 第二个元素
let z = tup.2; // 第三个元素
println!("x={x}, y={y}, z={z}");

特殊元组:单元类型 ()

  • 一个空的元组 (),读作 “unit”。
  • 它既是也是类型
  • 当一个函数不返回任何有意义的值时,它会隐式返回 ()
    fn do_something() {println!("我做了点事!");// 没有 return 语句,函数隐式返回 ()
    }
    
2. 数组积木(array

数组就像一个同质的、固定大小的盒子,所有格子必须装相同类型的东西。

  • 用方括号 [ ] 创建。
  • 所有元素类型必须相同。
  • 大小固定,创建后不能改变。
  • 数据通常分配在上,访问非常快。

例子

// 创建数组
let a = [1, 2, 3, 4, 5]; // 类型是 [i32; 5]// 显式类型注解
let a: [i32; 5] = [1, 2, 3, 4, 5];// 用同一个值初始化所有元素
let a = [3; 5]; // 等同于 [3, 3, 3, 3, 3]// 访问数组元素(通过索引)
let first = a[0]; // 第一个元素
let second = a[1]; // 第二个元素
println!("第一个元素是:{first}");

**数组 vs 向量 **(Vec)

  • 数组:大小固定,栈上分配,性能极高。适合大小已知且不变的场景,比如一周的天数、一年的月份。
    let months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun","Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]; // 12个月,固定!
    
  • **向量 **(Vec):大小可变,堆上分配。当你不确定需要多少元素,或者元素会增减时,用 Vec。这是标准库提供的类型。

数组越界:Rust 的“安全护栏”

这是 Rust 内存安全的核心体现!尝试访问数组不存在的索引会怎样?

use std::io;fn main() {let a = [1, 2, 3, 4, 5];println!("请输入一个索引 (0-4):");let mut input = String::new();io::stdin().read_line(&mut input).expect("读取失败");let index: usize = input.trim().parse().expect("请输入数字");let element = a[index]; // ⚠️危险操作!如果 index >= 5 会怎样?println!("元素是:{element}");
}
  • 结果:如果你输入 10,程序不会偷偷访问内存垃圾,而是会立刻 panic(崩溃),并清晰地告诉你:
    thread ‘main’ panicked at ‘index out of bounds: the len is 5 but the index is 10’
  • 为什么这很重要?在 C/C++ 等语言中,这种越界访问可能导致程序读取或写入非法内存,造成安全漏洞(如缓冲区溢出攻击)。Rust 通过这种“快速失败”机制,在运行时保护你,确保内存访问是安全的。

总结:Rust 数据类型的“设计哲学”

通过学习这些数据类型,我们可以看到 Rust 的核心思想:

  1. 明确性与安全性:类型必须清晰(静态类型),默认不可变,访问越界会 panic。这些规则在编译时和运行时帮你抓住错误。
  2. 性能与控制:提供了从 u8i128 的精细整数选择,isize/usize 用于系统编程,数组在栈上分配以获得极致性能。
  3. 现代性char 支持 Unicode,让程序天生支持多语言。
  4. 组合性:通过元组和数组,可以轻松组合数据。而 Vec 等标准库类型则提供了更高级的抽象。
  5. 零成本抽象:这些类型和检查带来的安全性,几乎没有运行时性能损失。

现在,你已经掌握了 Rust 构建程序的“基本积木”。记住,选择正确的“积木”(数据类型)是写出高效、安全、可维护代码的第一步!

http://www.dtcms.com/a/355343.html

相关文章:

  • Python Discord Logo
  • 【SpringAI】快速上手,详解项目快速集成主流大模型DeepSeek,ChatGPT
  • 操作系统-基础知识面试常见篇
  • 算法之排序
  • java后端的各种注解
  • 基于 PyTorch 构建 Dataset 与 DataLoader:从 TXT 文件读取到新增类别全流程指南
  • AI大模型企业落地指南-笔记02
  • Spring 框架中事务传播行为的定义
  • 146. LRU缓存
  • python使用sqlcipher4对sqlite数据库加密
  • 【论文阅读】基于人工智能的下肢外骨骼辅助康复方法研究综述
  • 【电源专题】隐形守护者:防爆锂电池如何守护高危环境的安全防线
  • UE5提升分辨率和帧率的方法
  • 网站日志里面老是出现{pboot:if((\x22file_put_co\x22.\x22ntents\x22)(\x22temp.php\x22.....
  • Leetcode 深度优先搜索 (15)
  • 【大前端】React Native(RN)跨端的原理
  • 比较两个字符串的大小
  • 使用CDN后如何才不暴露IP
  • EtherNet/IP 转 Modbus 协议网关(三格电子)
  • SOME/IP-SD通信中的信息安全保证
  • leetcode_73 矩阵置零
  • (LeetCode 面试经典 150 题) 103. 二叉树的锯齿形层序遍历(广度优先搜索bfs)
  • [n8n] 工作流数据库管理SQLite | 数据访问层-REST API服务
  • 解决PyCharm打开PowerShell终端报错找不到conda-hook.ps1文件
  • 前端javascript在线生成excel,word模板-通用场景(免费)
  • Spring Boot 定时任务入门
  • 使用Java实现PDF文件安全检测:防止恶意内容注入
  • ubuntu20安装lammps
  • PDFMathTranslate,完全免费的电脑 PDF 文档翻译软件
  • 怎么保护信息安全?技术理论分析