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

Rust 学习笔记 - 详解数据类型

前言

任何一门编程语言几乎都脱离不了:变量、基本类型、函数、注释、循环、条件判断,这是一门编程语言的语法基础,只有当掌握这些基础语法及概念才能更好的学习 Rust。

标量类型(Scalar Types)

在 Rust 中,标量类型代表单个值,Rust 有四种基本的标量类型:整型、浮点型、布尔类型和字符类型。

整数类形

整数是没有小数部分的数字,可以是正数、负数或零。整数类型分为两大类:有符号无符号有符号整数可以存储包括负数在内的值,而无符号整数只能存储零和正数。

fn main() {let x: i32 = -123; // 有符号整数let y: u32 = 456; // 无符号整数
}

整数类型参照:

长度有符号整数无符号整数
8-biti8u8
16-biti16u16
32-biti32u32
64-biti64u64
128-biti128u128
archisizeusize

isizeusize 两种整数类型的位长度取决于所运行的平台,如果是 32 位架构的处理器将使用 32 位长度整型 (即 i32 / u32),64 位架构的处理器上使用 64 为长度整型 (即 i64 / u64)。

整数类型具有明确的大小(取值范围),每个有符号整数类型可以存储 − 2 n − 1 -2^{n-1} 2n1 2 n − 1 − 1 2^{n-1} - 1 2n11,其中 n 为数据类型的位数,每个无符号整数类型可以存储 0 到 2 n − 1 2^{n} - 1 2n1

举个🌰:

  • i8 可以存储 − 2 8 − 1 -2^{8-1} 281 2 8 − 1 − 1 2^{8-1} - 1 2811 的数字,即: -128 到 127。
  • u8 可以存储 0 到 2 8 − 1 2^{8} - 1 281 的数字,即: 0 到 255。

字面量表示:

整数字面量可以通过不同的进制来表示,包括十进制、十六进制、八进制、二进制,以及字节(只适用于 u8)。

进制前缀示例
十进制98_222
十六进制0x0xff
八进制0o0o77
二进制0b0b111_0000
字节(u8 专用)bb'A'

注意:在 Rust 中,数字可以使用 _ 作为可视分隔符来提高可读性,编译器在处理数值时会忽略这些 _

浮点类型

浮点数是用来处理带有小数部分的数值。Rust 提供了两种基本的浮点类型,分别是 f32 和 f64,其中 f32 是单精度浮点类型,f64 是双精度浮点类型。Rust 中的浮点类型遵循 IEEE-754 标准。

fn main() {let x: f32 = 3.14; // f32 单精度浮点数let y: f64 = 2.71828; // f64 双精度浮点数let z = 2.71828; // 默认是 f64 双精度浮点数
}

f32 类型

f32 类型的浮点数是单精度浮点数,占用 32 位(4 字节)的内存空间。它的范围大约是 1.4E-45 到 3.4E+38,精度大约有 6-7 位十进制数。f32 类型的浮点数对于需要较高性能但不需要非常高精度的场景来说是一个不错的选择,因为它在处理速度和内存使用上都比 f64 更加高效。

f64 类型

f64 类型的浮点数是双精度浮点数,占用 64 位(8 字节)的内存空间。它的范围大约是 4.9E-324 到 1.8E+308,精度大约有 15-16 位十进制数。相比 f32f64 提供了更大的数值范围和更高的精度,适合对数值精度要求较高的计算任务。由于在现代 CPU 架构中,f64 的性能通常也非常高效,所以 Rust 默认的浮点类型就是 f64

浮点数的字面量表示法

浮点数可以使用字面量表示法来表示,例如:

  • 直接给出小数:3.14
  • 使用科学记数法:2.5e10 或 2.5E10 表示 2.5 × 10¹⁰
  • 在数字中使用下划线以提高可读性:1_000.75_001

特点和使用注意事项

  • 浮点数类型具备加 (+)、减 (-)、乘 (*)、除 (/)、求余 (%) 等算术运算能力。
  • 浮点数在运算时可能会出现“舍入错误”,这是因为许多实数不能被精确表示为 f32 或 f64 类型的数值。这类舍入错误是所有使用 IEEE-754 标准的浮点数表示法的编程语言的通病。
  • 浮点数比较需要特别注意,直接比较两个浮点数是否相等 (==) 可能会因为舍入误差导致不符合预期的结果。在涉及浮点数比较的时候,通常需要判断两个数的差值是否足够小。

布尔类型

布尔(Boolean)类型用 bool 表示,它是最简单的类型,只有两个值:true 和 false。布尔类型通常用于执行逻辑操作,条件判断和控制流程(例如,if 条件语句和循环控制)

fn main() {let t: bool = true;let f: bool = false;
}

基础

  • 类型名为 bool
  • 取值范围仅为 true 或 false
  • 布尔值用一个字节(1 byte 或 8 bits)来存储

字面量表示法

  • true 表示逻辑真。
  • false 表示逻辑假。

操作

布尔类型支持多种逻辑操作,包括但不限于:

  • 逻辑与 (&&): 当两个操作数都为 true 时,返回 true;否则返回 false
  • 逻辑或 (||): 只要一个操作数为 true,就返回 true;如果两个都为 false,则返回 false
  • 逻辑非 (!): 如果操作数为 true,返回 false;如果为 false,返回 true
let a = true;
let b = false;let and_result = a && b; // 返回 false
let or_result = a || b; // 返回 true
let not_result = !a; // 返回 false

字符类型

字符类型(char)用于表示单个 Unicode 标量值,这意味着它可以表示比 ASCII 更广泛的字符集。在 Rust 中,字符(char)是通过单引号(')来表示的,而字符串(String 或 &str)是通过双引号(")来表示的。

fn main() {let c: char = 'z';let z: char = 'ℤ'; // Unicode值let heart_eyed_cat = '😻';
}

基础

  • 类型名为 char
  • char 类型在 Rust 中是四个字节的大小,即 32 位(与 UTF-32 编码相同)。这是因为 char 需要能表示任意一个 Unicode 标量值,其范围从 U+0000 到 U+D7FF 和 U+E000 到 U+10FFFF
  • 每个字符是单独的 char 类型实例,并且占用 4 个字节的存储空间。这与其他一些语言中的字符类型(例如 C/C++ 中的 char)不同,其通常是基于 ASCII 并且仅占用 1 个字节。

字面量表示法

  • 普通字符:'a''Z''7' 等。
  • 特殊字符:可以使用转义序列表示,如换行符 '\n',制表符 '\t',单引号 '\'',反斜杠 '\\' 等。
  • Unicode 字符:使用 \u{} 转义和大括号内的十六进制数值来表示,如 '好' 可以用 '\u{597D}' 表示。

操作

  • char 类型的值可以直接参与比较操作(==, !=<>, 等)。
  • char 类型拥有多种方法用于检查字符的属性(例如 is_alphabeticis_numeric 等)。
let c1 = 'A';
let c2 = '\u{597D}'; // 表示 "好"if c1.is_alphabetic() {println!("{} 是字母", c1);
}if c2.is_numeric() {println!("{} 是数字", c2);
}

复合类型(Compound Types)

复合类型可以将多个值组合成一个类型。Rust 主要有两种复合类型:元组(Tuple)和数组(Array)。

元组(Tuple)

元组是可以包含多个不同类型值的一种集合。元组的长度固定,一旦声明,它的长度不会改变。

声明元组

let tup: (i32, f64, char) = (500, 6.4, 'y');

在这个例子中,tup 是一个元组,包含了一个 i32 类型的整数、一个 f64 类型的浮点数,以及一个 char 类型的字符。

元组解构

元组可以被解构(destructured),为其内部的每个值匹配一个变量名称。

let tup = (500, 6.4, 1);
let (x, y, z) = tup;
println!("The value of y is: {}", y); // 输出 6.4

通过索引访问元组元素

也可以使用索引访问元组中的元素。

let five_hundred = tup.0;
let six_point_four = tup.1;
let y = tup.2;

数组(Array)

数组是有多个相同类型值组成的集合。与元组一样,数组的长度也是固定的,Rust 的数组一旦声明,它的长度不能改变。

声明数组

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

这里,a 是一个整型数组,包含五个整数。

带类型注解的数组

你也可以在声明数组时添加类型注解,指明数组中的元素类型以及数组的长度。

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

初始化数组

如果数组中的每个元素都是相同的值,可以使用以下方式进行初始化。

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

这里 a 是一个整型数组,包含五个都是数字3的元素。

访问数组元素

通过索引来访问数组中的元素。

let first = a[0]; // 访问第一个元素
let second = a[1]; // 访问第二个元素

在访问时,如果索引超出了数组的边界,Rust 会在编译时或运行时(取决于索引是否为常量表达式)抛出错误,这是 Rust 的安全性特性之一。

选择元组还是数组?

  • 当想要在一个复合类型中包含多个不同类型的值时,应当使用元组。
  • 当需要一个包含多个相同类型值的集合时,应当使用数组。

元组非常适合用于有结构的数据,而数组非常适合用于有相同数据类型要求的连续数据序列。通过使用元组和数组,可以创建出符合你需要的各种数据结构。

自定义类型(Custom Types)

自定义类型主要指的是通过使用结构体(struct)和枚举(enum)来创建的数据类型。这两种类型允许开发者定义和使用更丰富且符合业务逻辑的数据结构。

结构体(Struct)

结构体是将零个或多个不同类型的数据聚合到一个复合类型中的一种方式。他们在概念上类似于其他语言中的类(但没有继承功能),是用于创建自定义数据类型的集合。

声明结构体

struct User {username: String,email: String,sign_in_count: u64,active: bool,
}

在这个例子中,User 结构体包含了四个字段,每个字段都有指定的类型。

实例化结构体

要使用结构体,你需要创建其实例并为其字段提供相应的值。

let user1 = User {email: String::from("admin@example.com"),username: String::from("ziyang"),active: true,sign_in_count: 1,
};

可以通过派生特性 #[derive(Debug)] 来允许结构体实例在使用 println! 宏时使用 {:?} 或 {:#?} 格式化输出。

枚举(Enum)

枚举允许定义一个类型,它可以是几个不同的变体中的一个。枚举在那些一次只能有一个值从多个可能的值中选取的情况下特别有用。

声明枚举

enum IpAddrKind {V4,V6,
}

这里,IpAddrKind 枚举有两个变体:V4 和 V6

枚举也可以关联数据。

enum IpAddr {V4(String),V6(String),
}

甚至每个枚举变体关联的数据都可以有不同类型。

enum Message {Quit,Move { x: i32, y: i32 },Write(String),ChangeColor(i32, i32, i32),
}

枚举类的使用

let four = IpAddrKind::V4;
let six = IpAddrKind::V6;

用 match 控制流运算符来处理枚举有助于确保你考虑到了所有可能的情况。

Never (!

Rust 中有一个表示"永不返回"的特殊类型,称作 ! 类型,也就是所谓的 “Never” 类型。这个类型用于那些不返回任何值的函数,或者那些不会正常返回,因为它们会无限循环或者结束当前进程的函数。

Never 类型用于表示永不返回的函数。这有助于 Rust 进行更严格的类型检查和控制流分析。

示例:

fn forever() -> ! {loop {// 无限循环,永不返回}
}

在这个示例中,forever 函数有一个 ! 返回类型,表示此函数将永远不会返回一个值。

Never 类型 (!) 的用途

  1. 控制流运算符:
    ! 类型主要与 Rust 中的 match 表达式一起用于保证所有可能情况都已处理。如果 match 的一个分支结束于一个永不返回的函数,Rust 知道不需要返回值。这就是所谓的"穷尽性检查"(exhaustiveness checking)。

  2. 错误处理:
    经常与 panic! 宏一起使用,它会使当前线程崩溃,并可以带有一个错误消息。由于 panic! 永远不会返回,它的返回类型是 !

结语

本章深入讲解了 Rust 中的标量类型、复合类型、自定义类型以及特殊的 never 类型。此外,还有指针类型、动态大小类型、函数类型等其他重要的数据类型将在后续文章中陆续进行逐一介绍。

相关文章:

Rust 学习笔记 - 详解数据类型

前言 任何一门编程语言几乎都脱离不了&#xff1a;变量、基本类型、函数、注释、循环、条件判断&#xff0c;这是一门编程语言的语法基础&#xff0c;只有当掌握这些基础语法及概念才能更好的学习 Rust。 标量类型&#xff08;Scalar Types&#xff09; 在 Rust 中&#xff…...

构建本地yum源

下载repo数据文件 根据需要修改下载路径和reposync参数 #!/bin/bashlocal_path/repo/remote/rhel9 enabled_repos$(yum repolist enabled | awk NR>3{print $1}) tempfile$(mktemp -t reposync.XXXX)check() {echo "目标目录剩余空间: $(df -h ${local_path} | awk …...

常用的正则表达式,收藏必备!!!

正则表达式是一种强大的文本模式匹配工具&#xff0c;用于在字符串中查找、替换和验证特定模式的文本。下面是一些常用的正则表达式示例&#xff1a; 匹配Email地址&#xff1a; ^[a-zA-Z0-9._%-][a-zA-Z0-9.-]\.[a-zA-Z]{2,}$匹配URL&#xff1a; ^(https?|ftp)://[^\s/$.?#…...

js---webAPI

01 声明变量 js组成&#xff1a; DOM:操作网页内容的,开发页面内容特效和实现用户交互 BOM: DOM树&#xff1a;将 HTML 文档以树状结构直观的表现出来&#xff0c;我们称之为文档树或 DOM 树 文档树直观的体现了标签与标签之间的关系 CSS获取元素的方法 document.querySele…...

git的常用命令有哪些?

Git 是一个流行的分布式版本控制系统&#xff0c;用于跟踪文件的变化、协作开发和管理代码。以下是一些常用的 Git 命令&#xff1a; 创建和克隆仓库&#xff1a; git init&#xff1a;在当前目录初始化一个新的 Git 仓库。git clone <仓库URL>&#xff1a;克隆一个远程仓…...

《动手学深度学习(PyTorch版)》笔记8.5

注&#xff1a;书中对代码的讲解并不详细&#xff0c;本文对很多细节做了详细注释。另外&#xff0c;书上的源代码是在Jupyter Notebook上运行的&#xff0c;较为分散&#xff0c;本文将代码集中起来&#xff0c;并加以完善&#xff0c;全部用vscode在python 3.9.18下测试通过&…...

【蓝桥杯单片机入门记录】LED灯(附多个例程)

目录 一、LED灯概述 1.1 LED发光原理 1.2电路原理图 1.3电路实物图 1.4 开发板LED灯原理图 1.4.1共阳极LED灯操控原理&#xff08;本开发板&#xff09; &#xff08;非实际原理图&#xff0c;便于理解版本&#xff09;由图可以看出&#xff0c;每个LED灯的左边&#xf…...

c语言简单json库

文章目录 写在前面头文件源代码使用示例 写在前面 用c语言实现的一个简单json库&#xff0c;极其轻量 仅1个四百多行源码的源文件&#xff0c;和1个头文件 支持对象、数组、数值、字符串类型 github仓库 头文件 对主要的json API的声明 #ifndef ARCOJSON_ARCOJSON_H #defin…...

Linux操作系统基础(七):Linux常见命令(二)

文章目录 Linux常见命令&#xff08;二&#xff09; 一、kill命令 二、ifconfig命令 三、clear命令 四、重启与关机命令 五、which命令 六、hostname命令 七、grep命令 八、|管道 九、useradd命令 十、userdel命令 十一、tar命令 十二、su命令 十三、ps命令 Linu…...

进程状态

广义概念&#xff1a; 从广义上来讲&#xff0c;进程分为新建、运行、阻塞、挂起、退出五个状态&#xff0c;其中新建和退出两个状态可以直接理解字面意思。 运行状态&#xff1a; 这里涉及到运行队列的概念&#xff0c;CPU在读取数据的时候&#xff0c;需要把内存中的进程放入…...

STM32固件库简介与使用指南

1. STM32官方标准固件库简介 STM32官方标准固件库是由STMicroelectronics&#xff08;ST&#xff09;提供的一套软件开发工具&#xff0c;旨在简化STM32微控制器的软件开发过程。该固件库提供了丰富的功能和模块&#xff0c;涵盖了STM32微控制器的各种外设&#xff0c;包括但不…...

【开源】SpringBoot框架开发智能教学资源库系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 数据中心模块2.2 课程档案模块2.3 课程资源模块2.4 课程作业模块2.5 课程评价模块 三、系统设计3.1 用例设计3.2 数据库设计3.2.1 课程档案表3.2.2 课程资源表3.2.3 课程作业表3.2.4 课程评价表 四、系统展示五、核心代…...

融资项目——获取树形结构的数据

如下图所示&#xff0c;下列数据是一个树形结构数据&#xff0c;行业中包含若干子节点。表的设计如下图&#xff0c;设置了一个id为1的虚拟根节点。&#xff08;本树形结构带虚拟根节点共三层&#xff09; 实现逻辑&#xff1a; 延时展示方法&#xff0c;先展现第二层的信息&a…...

Crypto-RSA2

题目&#xff1a;&#xff08;BUUCTF在线评测 (buuoj.cn)&#xff09; 已知e,n,dp/(dq),c求明文: 首先有如下公式&#xff1a; dp ≡ d mod (p-1) &#xff0c;ed ≡ 1 mod φ(n) &#xff0c;npq &#xff0c;φ(n)(p-1)(q-1) python代码实现如下&#xff1a; import libnu…...

IEEE Internet of Things Journal投稿经验

期刊名&#xff1a;IEEE Internet of Things Journal 期刊分区&#xff1a;中科院一区 Top 影响因子&#xff1a;10.6 投稿状态 &#xff08;1&#xff09;2023.11.3&#xff0c;投稿成功&#xff0c;状态为&#xff1a;under review&#xff08;大u大r&#xff09;&#xff1…...

实例分割论文阅读之:FCN:《Fully Convolutional Networks for Semantica Segmentation》

论文地址:https://openaccess.thecvf.com/content_cvpr_2015/papers/Long_Fully_Convolutional_Networks_2015_CVPR_paper.pdf 代码链接&#xff1a;https://github.com/pytorch/vision 摘要 卷积网络是强大的视觉模型&#xff0c;可以产生特征层次结构。我们证明&#xff0c…...

apk反编译修改教程系列---简单去除apk登陆 修改vip与一些反编译基础常识【十二】

往期教程&#xff1a; 安卓玩机-----反编译apk 修改apk 去广告 去弹窗等操作中的一些常识apk反编译修改教程系列-----修改apk应用名称 任意修改名称 签名【一】 apk反编译修改教程系列-----任意修改apk版本号 版本名 防止自动更新【二】 apk反编译修改教程系列-----修改apk中…...

网络安全习题集

第一章 绪论 4 ISO / OSI 安全体系结构中的对象认证安全服务使用&#xff08; C ) 机制来完成。 A &#xff0e;访问控制 B &#xff0e;加密 C &#xff0e;数字签名 D &#xff0e;数据完整性 5 身份鉴别是安全服务中的重要一环&#xff0c;以下关于身份鉴别的叙述不正确的是…...

C++中的volatile:穿越编译器的屏障

C中的volatile&#xff1a;穿越编译器的屏障 在C编程中&#xff0c;我们经常会遇到需要与硬件交互或多线程环境下访问共享数据的情况。为了确保程序的正确性和可预测性&#xff0c;C提供了关键字volatile来修饰变量。本文将深入解析C中的volatile关键字&#xff0c;介绍其作用、…...

(07)Hive——窗口函数详解

一、 窗口函数知识点 1.1 窗户函数的定义 窗口函数可以拆分为【窗口函数】。窗口函数官网指路&#xff1a; LanguageManual WindowingAndAnalytics - Apache Hive - Apache Software Foundationhttps://cwiki.apache.org/confluence/display/Hive/LanguageManual%20Windowing…...

Chapter03-Authentication vulnerabilities

文章目录 1. 身份验证简介1.1 What is authentication1.2 difference between authentication and authorization1.3 身份验证机制失效的原因1.4 身份验证机制失效的影响 2. 基于登录功能的漏洞2.1 密码爆破2.2 用户名枚举2.3 有缺陷的暴力破解防护2.3.1 如果用户登录尝试失败次…...

Debian系统简介

目录 Debian系统介绍 Debian版本介绍 Debian软件源介绍 软件包管理工具dpkg dpkg核心指令详解 安装软件包 卸载软件包 查询软件包状态 验证软件包完整性 手动处理依赖关系 dpkg vs apt Debian系统介绍 Debian 和 Ubuntu 都是基于 Debian内核 的 Linux 发行版&#xff…...

电脑插入多块移动硬盘后经常出现卡顿和蓝屏

当电脑在插入多块移动硬盘后频繁出现卡顿和蓝屏问题时&#xff0c;可能涉及硬件资源冲突、驱动兼容性、供电不足或系统设置等多方面原因。以下是逐步排查和解决方案&#xff1a; 1. 检查电源供电问题 问题原因&#xff1a;多块移动硬盘同时运行可能导致USB接口供电不足&#x…...

linux 下常用变更-8

1、删除普通用户 查询用户初始UID和GIDls -l /home/ ###家目录中查看UID cat /etc/group ###此文件查看GID删除用户1.编辑文件 /etc/passwd 找到对应的行&#xff0c;YW343:x:0:0::/home/YW343:/bin/bash 2.将标红的位置修改为用户对应初始UID和GID&#xff1a; YW3…...

微服务商城-商品微服务

数据表 CREATE TABLE product (id bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 商品id,cateid smallint(6) UNSIGNED NOT NULL DEFAULT 0 COMMENT 类别Id,name varchar(100) NOT NULL DEFAULT COMMENT 商品名称,subtitle varchar(200) NOT NULL DEFAULT COMMENT 商…...

C++.OpenGL (10/64)基础光照(Basic Lighting)

基础光照(Basic Lighting) 冯氏光照模型(Phong Lighting Model) #mermaid-svg-GLdskXwWINxNGHso {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-GLdskXwWINxNGHso .error-icon{fill:#552222;}#mermaid-svg-GLd…...

初探Service服务发现机制

1.Service简介 Service是将运行在一组Pod上的应用程序发布为网络服务的抽象方法。 主要功能&#xff1a;服务发现和负载均衡。 Service类型的包括ClusterIP类型、NodePort类型、LoadBalancer类型、ExternalName类型 2.Endpoints简介 Endpoints是一种Kubernetes资源&#xf…...

JVM虚拟机:内存结构、垃圾回收、性能优化

1、JVM虚拟机的简介 Java 虚拟机(Java Virtual Machine 简称:JVM)是运行所有 Java 程序的抽象计算机,是 Java 语言的运行环境,实现了 Java 程序的跨平台特性。JVM 屏蔽了与具体操作系统平台相关的信息,使得 Java 程序只需生成在 JVM 上运行的目标代码(字节码),就可以…...

腾讯云V3签名

想要接入腾讯云的Api&#xff0c;必然先按其文档计算出所要求的签名。 之前也调用过腾讯云的接口&#xff0c;但总是卡在签名这一步&#xff0c;最后放弃选择SDK&#xff0c;这次终于自己代码实现。 可能腾讯云翻新了接口文档&#xff0c;现在阅读起来&#xff0c;清晰了很多&…...

NPOI操作EXCEL文件 ——CAD C# 二次开发

缺点:dll.版本容易加载错误。CAD加载插件时&#xff0c;没有加载所有类库。插件运行过程中用到某个类库&#xff0c;会从CAD的安装目录找&#xff0c;找不到就报错了。 【方案2】让CAD在加载过程中把类库加载到内存 【方案3】是发现缺少了哪个库&#xff0c;就用插件程序加载进…...