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 类型。此外,还有指针类型、动态大小类型、函数类型等其他重要的数据类型将在后续文章中陆续进行逐一介绍。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/685523.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

12-资源注解annotations和安全行下文securityContext(了解即可)

一、资源注解annotations 资源注解&#xff0c;annotations就是对资源进行注释&#xff1b; 应用场景&#xff1a; 给资源&#xff08;例如pod资源&#xff09;提供配置信息&#xff0c;类似于帮助信息&#xff1b; 早期使用比较多&#xff0c;很多开源组件一般都会使用&#x…

交大论文下载器

原作者地址&#xff1a; https://github.com/olixu/SJTU_Thesis_Crawler 问题&#xff1a; http://thesis.lib.sjtu.edu.cn/的学位论文下载系统&#xff0c;该版权保护系统用起来很不方便&#xff0c;加载起来非常慢&#xff0c;所以该下载器实现将网页上的每一页的图片合并…

Lua:面向对象/C之间的交互

前段时间对平台的任务感兴趣&#xff0c;其要求是一周内12篇博文&#xff0c;尝试了之后发现还是太敷衍了&#xff0c;之后还是回归到内容本身上来&#xff0c;尽量保证一篇博文的内容能涵盖足够多的知识点或者足够深的思考成分。 面向对象 面向对象主要有三个方面&#xff1…

【JavaScript】Cookies

文章目录 1. 什么是Cookies2. Cookies的基本属性3. JavaScript中的Cookies操作设置Cookies读取Cookies获取特定Cookies的值删除Cookies 4. Cookies的应用场景记住用户登录状态存储用户偏好设置跨页面数据传递 5. 安全性注意事项6. 总结 在 Web 开发中&#xff0c; Cookies 是一…

索引失效场景

在数据库系统中&#xff0c;索引用于加速查询处理&#xff0c;但在某些情况下&#xff0c;即使存在索引&#xff0c;数据库查询优化器&#xff08;Query Optimizer&#xff09;可能选择不使用它们。这称之为“索引失效”。以下列出了常见的索引失效场景&#xff0c;并进行了解析…

GPU独显下ubuntu屏幕亮度不能调节解决方法

GPU独显下屏幕亮度不能调节&#xff08;假设你已经安装了合适的nvidia显卡驱动&#xff09;&#xff0c;我试过修改 /etc/default/grub 的 GRUB_CMDLINE_LINUX_DEFAULT"quiet splash acpi_backlightvendor" &#xff0c;没用。修改和xorg.conf相关的文件&#xff0c;…

不花一分钱,在 Mac 上跑 Windows(M1/M2 版)

这是在 MacOS M1 上体验最新 Windows11 的效果&#xff1a; VMware Fusion&#xff0c;可以运行 Windows、Linux 系统&#xff0c;个人使用 licence 免费 安装流程见 &#x1f449; https://zhuanlan.zhihu.com/p/452412091 从申请 Fusion licence 到下载镜像&#xff0c;再到…

MySQL性能调优篇(10)-数据库备份与恢复策略

MySQL数据库备份与恢复策略 数据库备份与恢复是数据库管理中非常重要的一环&#xff0c;对于保障数据的安全性和可靠性起着至关重要的作用。本文将介绍MySQL数据库备份与恢复的策略&#xff0c;包括备份类型、备份方法以及恢复策略。 1. 备份类型 1.1 完整备份 完整备份是备…

安装 Windows Server 2019

1.镜像安装 镜像安装:Windows Server 2019 2.安装过程(直接以图的形式呈现) 先选择""我没有产品密钥"",选择桌面体验 选择自定义 设置密码后继续 安装成功

SpringUtils 工具类,方便在非spring管理环境中获取bean

应用场景&#xff1a; 1 可用在工具类中&#xff0c; 2 spring【Controller,service】环境中&#xff0c; 3 其中的一个方法getAopProxy可获得代理对象&#xff0c;需要将 EnableAspectJAutoProxy(exposeProxy true) 允许获取代理对象 import org.springframework.aop.framew…

07-k8s中secret资源02-玩转secret

一、回顾secret资源的简单实用 第一步&#xff1a;将想要的数据信息【key&#xff1a;value】中的value值&#xff0c;使用base64编码后&#xff0c;写入secret资源清单中&#xff1b; 第二步&#xff1a;创建secret资源&#xff1b; 第三步&#xff1a;pod资源引用secret资源&…

第2讲springsecurity+vue通用权限系统

阿里云 maven阿里云镜像 <?xml version"1.0" encoding"UTF-8"?><!-- Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for addition…

MySQL的配置文件my.cnf正常的配置项目

my.cnf&#xff08;或my.ini&#xff09;是MySQL的配置文件&#xff0c;其中包含了多种设置&#xff0c;用于控制MySQL服务器的运行方式。以下是my.cnf中一些常见的配置项目&#xff1a; 服务器设置 - [mysqld]&#xff1a;服务器的配置部分。 - user&#xff1a;指定M…

C++,stl,常用排序算法,常用拷贝和替换算法

目录 1.常用排序算法 sort random_shuffle merge reverse 2.常用拷贝和替换算法 copy replace replace_if swap 1.常用排序算法 sort 默认从小到大排序 #include<bits/stdc.h> using namespace std;int main() {vector<int> v;v.push_back(1);v.push_ba…

速盾网络:cdn加速服务器代理分销

CDN&#xff08;Content Delivery Network&#xff09;是一种分布式网络架构&#xff0c;旨在提供快速、安全和高效的内容传输和分发服务。CDN加速服务器代理分销是指将CDN网络资源转售给其他企业或个人&#xff0c;以帮助他们实现内容加速和分发的目标。 CDN加速服务器代理分…

基于Web技术的家居室内温湿度监测系统

设计一个基于Web技术的家居室内温湿度监测系统涉及前端和后端开发&#xff0c;以及与硬件传感器的集成。以下是一个简单的设计概述&#xff1a; ### 1. 系统架构 - **前端**: 用户界面&#xff0c;用于显示实时数据和历史记录&#xff0c;可通过Web浏览器访问。 - **后端**: 服…

Leetcode 647. 回文子串

题意理解&#xff1a; 给你一个字符串 s &#xff0c;请你统计并返回这个字符串中 回文子串 的数目。 回文字符串 是正着读和倒过来读一样的字符串。 子字符串 是字符串中的由连续字符组成的一个序列。 具有不同开始位置或结束位置的子串&#xff0c;即使是由相同的字符组成&am…

【友塔笔试面试复盘】八边形取反问题

问题&#xff1a;一个八边形每条边都是0&#xff0c;现在有取反操作&#xff0c;选择一条边取反会同时把当前边和2个邻边取反&#xff08;如果是0变为1&#xff0c;如果是1变为0&#xff09; 现在问你怎么取反能使得八条边都变为1. 当时陷入了暴力递归漩涡&#xff0c;给出一个…

问题:内存时序参数 CASLatency 是() #学习方法#微信#微信

问题&#xff1a;内存时序参数 CASLatency 是&#xff08;&#xff09; A&#xff0e;行地址控制器延迟时间 B&#xff0e;列地址至行地址延迟时间 C&#xff0e;列地址控制器预充电时间 D&#xff0e;列动态时间 参考答案如图所示

[职场] 求职如何设置预期 #笔记#经验分享

求职如何设置预期 在求职的道路上&#xff0c;无论处于哪个年龄阶段&#xff0c;合理的就业期望值才能使我们的愿望与社会的需求相吻合&#xff0c;才能让自己在今后的工作中发挥出最大的实力与能力。 一、结合测评软件&#xff0c;明确求职目标 根据霍兰德职业兴趣测试结果&a…