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

Rust语言入门教程(四) - 数据类型

标量类型(Scalar Types)

在Rust中,一共有4中标量类型, 也就是基本数据类型,分别是:

  • 整型(Integers)
  • 浮点型(Floats)
  • 布尔型(Boolean)
  • 字符型(Characters)

整型

无符号整型(Unsigned)有符号整型(Signed)
u8i8
u16i16
u32i32
u64i64
u128i128
usizeisize

其中分为无符号整型(以u开头),和有符号整型(以i开头),后面的数据代表该类型在内存中占多少bits. 其中usize类型是个例外,usize 类型的位数取决于目标平台的架构:

  • 在 32 位架构上,usize 是 32 位的。
  • 在 64 位架构上,usize 是 64 位的。

usize 类型通常用于索引集合和与内存大小相关的操作,其大小与平台的内存寻址能力相匹配,确保在任何平台上都能高效地进行这些操作。例如可以用于arrayvector的索引的类型。isizeusize类似,只不过它是有符号的而已。

如果在声明一个整型变量时没有显式的标准类型的话,整型变量默认会被Rust识别为i32类型,因为这个类型的性能通常是最好的,即使是在64位的系统上也是如此。

需要注意的是,虽然Rust有这些整型,但根据你的系统位数不同,有的整型类型可能不被支持,比如在一个16-bit的系统中,就只支持16位及以下的整型类型(u8,i8, u16,i16)和usize, isize.

整型与进制

进制写法示例说明
十进制(Decimal)100000直接以数字开头
十六进制(Hex)0xdeadbeef0x开头的数字会被识别为16进制
八进制(Octal)0o775432110o开头的数字会被识别为8进制
二进制(Binary)0b111100110b开头的数字会被识别为二进制
字节(byte)b’A’用b开头,单引号内为一个ASCII码范围内的字符,因此byte类型在Rust中跟u8类型是等价的,因为他们都是0-255之间的数字

Rust会自动忽略在数字中出现的_, 因此可以在数字中间任意位置加上_以方便我们阅读代码,例如:

进制写法示例加下划线写法
十进制(Decimal)100000100_000
十六进制(Hex)0xdeadbeef0xde_ad_be_ef
八进制(Octal)0o775432110o7754_3211
二进制(Binary)0b111100110b1_1_1_1_0_0_1_1

浮点型

浮点类型比整型简单许多,只有两种类型:

  • f32
  • f64
    他们之间的区别就是精度上的不同,默认情况下浮点数的类型是f64, 但是如果你的操作系统位数是低于64位的, f64的性能就会很差,这是需要注意的一点。

浮点类型的格式遵循IEEE-754标准规范,由整数位,小数点和小数位组成,如:

3.1415926   // legal
.1			// illegal, 必须有整数位
0.1			// legal

数字类型的声明方法

在定义一个数字类型的变量时, 有两种标注类型的方法。 第一种与我们之前介绍变量声明的章节中一样:

let x: u16 = 5;
let y: f32 = 3.14;

第二种方法,也可以将类型作为后缀,放在值的后面,如下:

let x = 5u16;
let y = 3.14f32;

为了方便阅读,也可以像在上一节中所说的一样,在数字中加上_, 如下:

let x = 5_u16;
let y = 3.14_f32;

这种方法在我们需要给一些泛型函数传递指定类型的参数时很有帮助, 比如一个函数有一个参数x, 这个参数x的类型可以是u16 , 也可以是u32, 根据参数的类型不同,函数的行为会发生变化, 此时如果我需要传入的参数值为5, 那么我就需要为这个5指定类型,那么便可以写为5u16 或者 5u32

布尔型

布尔型只有两个可能的值:

  • true
  • false

注意都是小写。 可以如下定义一个布尔型变量:

let b: bool = true;
let c = false;

布尔型不是数字,因此不可以用于数学计算,除非用as关键词把它转换,例如:

fn main(){let x = 10 - true;println!("{}", x);
}

这样是会报错的, 但是改成下面这样就不会了:

fn main(){let x = 10 - true as u8;println!("{}", x);
}

上面的代码中true as u8会把布尔型转换成整型(1u8),因此最终程序输出的结果是9

字符型

char这个类型的命名并不准确,每个char类型的变量应该都是一个标准的unicode值, 例如下面的值都是合法的:

let my_letter = 'a';
let i_kratkoa = 'й' ;
let ideograph = '你';
let my_fire = '🔥'

如上, 一个char变量的值可能是一个英文字母,也可能是一个其他语言中的字母,也可能是一个汉字, 甚至可以是一个表情符号,还可能是一些不可打印的控制符号,只要它是在unicode可以表示的范围内,一个char类型的变量占4 bytes的空间。

其他语言中, string一般都是由char组成的, 但是在Rust中却不是。Rust中的String中的元素是UTF-8格式的,而char类型不是, 因此String并没有用到char类型。

我们的代码编辑器显示的源代码也是UTF-8格式的,因此,我们在代码中看到的一个字符,其实并不等同于Rust中的一个char

复合类型(Compound Types)

顾名思义, 复合类型就是把多个不同数据类型的值组合在一起,成为一个自定义的数据类型。

元组(Tuple)

我们要介绍的第一种复合类型是元组(tuple), 元组中可以存储多个不同类型的值,如下可以简单的声明并初始化一个元组:

let info = (1, 3.3, 999);

上面的元组中包含了3个数字,由于没有显式的标注变量类型, 根据我们前面的章节内容, 1999 会被自动识别为 i32型, 3.3会被自动识别为f64型。如果要显式的标注元组类型,那么我们可以自然而然的想到应该像这样做:

let info: (u8, f64, i32) = (1, 3.3, 999);

元组操作

在Rust中想要访问元组中的元素有两种方式, 第一种是用.号, 通常也被叫做字段访问操作符, 例如:

let info: (u8, f64, i32) = (1, 3.3, 999);
let jets = info.0;  // 1
let fuel = info.1;  // 3.3
let ammo = info.2;  // 999

我猜想Rust用.而不用[ ]来访问元组元素的原因,可能是为了暗示这样一个事实:元组成员的数据类型不一定是全部一样的。元组的字段是没有名称的,所以我们使用下标来访问元组成员, 和其他大多数编程语言一样, 元组的下标从0开始。

第二种访问元组成员的方法类似前面的章节中, 一次性为多个变量赋值,我们可以用一组与元组个数相同的变量直接解构一个元组,并将元组中的每个成员赋值给这些变量,如下:

let info: (u8, f64, i32) = (1, 3.3, 999);
// let jets = info.0;  // 1
// let fuel = info.1;  // 3.3
// let ammo = info.2;  // 999
let (jets, fuel, ammo) = info;

元组长度限制

在Rust中,并没有严格规定元组的长度限制。然而,值得注意的是,Rust 标准库为长度最多为 12 的元组实现了某些特质,比如 Debug 和 Clone。这意味着如果你有一个长度超过 12 的元组,你可能需要为这个元组手动实现这些特质,或者使用不同的数据结构。

举个例子,对于一个有 13 个元素的元组 (T1, T2, T3, …, T13),你可能无法直接使用 println!(“{:?}”, tuple) 来打印这个元组,因为 Debug 特质默认只为长度最多为 12 的元组实现。这并不是说你不能创建长度超过 12 的元组,只是意味着某些元组操作可能不如较短元组那样开箱即用。

数组(Array)

与元组不同的是, 数组中存储的是一组相同类型的值。下面是一个声明并初始化数组的简单示例:

let buf = [1, 2, 3];

如果想要初始化一个所有元素都相同的数组,也可以通过这种形式来书写: [元素值; 元素个数], 例如:

let buf = [0; 3] // 等价于 let buf = [0, 0, 0];

标注数组的数据类型的方式跟元组不同,只能用[元素类型; 数组长度] 这样的格式, 下面给出了正确和错误的示例:

let buf: [u8; 3] = [1, 2, 3]; 		// 正确
let buf: [u8, u8, u8] = [1, 2, 3];  // 错误

对于数组元素的索引,我们就跟其他语言一样,使用[下标]的格式了,例如:

buf[0]

数组长度限制

在 Rust 中,数组长度最好不要超过 32。 跟元组的长度限制类似,这主要是因为 Rust 标准库中对数组实现了某些特质(traits)的自动派生(derive)仅限于长度最多为 32 的数组。这些特质包括常用的 Debug、Clone、Hash、PartialEq、Eq、PartialOrd、Ord 等。

对于长度超过 32 的数组,这些特质就不会自动实现。这意味着如果你有一个长度超过 32 的数组,例如 [i32; 33],你将无法使用 println!(“{:?}”, array) 来打印这个数组,因为 Debug 特质没有为这样的数组实现。同样,你也不能自动获得数组的克隆、比较等能力。

这个限制源于 Rust 标准库的设计决策,目的是平衡编译时间和可用性。由于 Rust 在编译时需要为每种数组长度和每个特质生成特定的实现代码,过长的数组会显著增加编译器的负担,尤其是在编译大型项目时。

因此,当你需要长度超过 32 的数组时,通常推荐使用向量(Vec),向量是一个动态数组,可以容纳任意数量的元素,并且不受上述特质实现的限制。向量提供了灵活性和扩展性,适合于需要动态大小或长度未知的情况。在性能敏感的场合,或者当数组大小在编译时已知且不会变化时,固定长度的数组(如 [T; N])才是更好的选择。

小结

本章主要介绍了Rust的四种标量类型的使用方法与注意事项,以及元组与数组的基本知识,下一章将介绍Rust中的流控制语句。

相关文章:

Rust语言入门教程(四) - 数据类型

标量类型(Scalar Types) 在Rust中,一共有4中标量类型, 也就是基本数据类型,分别是: 整型(Integers)浮点型(Floats)布尔型(Boolean)字符型(Chara…...

华为云人工智能入门级开发者认证学习笔记

人工智能入门级开发者认证 人工智能定义 定义 人工智能 (Artificial Intelligence) 是研究、延伸和扩展人的智能的理论、方法、技术及应用系统的一门新的技术科学。 强人工智能 vs 弱人工智能 强人工智能:强人工智能观点认为有可能制造出真正能推理&#xff08…...

腾讯云发布新一代基于AMD处理器的星星海云服务器实例SA5

基础设施的硬实力,愈发成为云厂商的核心竞争力。 11月24日,腾讯云发布了全新一代星星海服务器。基于自研服务器的高密设计与硬件升级,对应云服务器SA5是全球首家搭载第四代AMD EPYC处理器(Bergamo)的公有云实例&#…...

算法通关村-----数论问题解析

最大公约数和最小公倍数 概念描述 最大公约数(GCD)是指两个或多个整数共有约数中的最大值。 最小公倍数(LCM)是指两个或多个整数共有的倍数中的最小值 方法介绍 碾转相除法 一种用于计算两个整数的最大公约数(GCD…...

wpf prism当中 发布订阅 IEventAggregator

先订阅后发布 private readonly IEventAggregator _eventAggregator; public LoginViewModel(ILoginService iloginService, IEventAggregator eventAggregator) {_iloginService iloginService;_eventAggregator eventAggregator;_eventAggregator.GetEvent<MessageEven…...

Angular中的getter函数

Angular 中的 getter 函数每次被调用时会返回一个新对象时&#xff0c;这些新对象并不使用同一个堆内存。详细解释一下&#xff1a; Getter 函数的作用是获取某个属性的值。在 Angular 中&#xff0c;getter 函数通常用于获取响应式数据&#xff08;例如 Observables 或 Signal…...

Python----函数的数据 拆包(元组和字典)

Python拆包&#xff1a; 就是把元组或字典中的数据单独的拆分出来&#xff0c;然后赋予给其他的变量。 拆包: 对于函数中的多个返回数据, 去掉 元组, 列表 或者字典 直接获取里面数据的过程。 元组的拆包过程 def func():# 经过一系列操作返回一个元组return 100, 200 …...

vim翻页快捷键

Vim翻页 整页 Ctrlf向下翻页&#xff0c;下一页&#xff0c;相当于Page DownCtrlb向上翻页&#xff0c;上一页&#xff0c;相当于Page Up 半页 Ctrld向下半页&#xff0c;下一半页&#xff0c;光标下移Ctrlu向上半页&#xff0c;上衣半页&#xff0c;光标上移 按行 Ctrle…...

死锁是什么?死锁是如何产生的?如何破除死锁?

1. 死锁是什么 多个线程同时被阻塞&#xff0c;它们中的一个或者全部都在等待某个资源被释放。由于线程被无限期地阻塞&#xff0c;因此程序不可能正常终止。 2. 死锁的三种典型情况 一个线程, 一把锁, 是不可重入锁, 该线程针对这个锁连续加锁两次, 就会出现死锁. 两个线程…...

给虚拟机配置静态id地址

1.令人头大的原因 当连接虚拟机的时候 地址不一会就改变&#xff0c;每次都要重新输入 2.配置虚拟机静态id地址 打开命令窗口执行 : vim /etc/sysconfig/network-scripts/ifcfg-ens33 按下面操作修改 查看自己子网掩码 3.重启网络 命令行输入 systemctl restart netwo…...

Mybatis-Plus 租户使用

Mybatis-Plus 租户使用 文章目录 Mybatis-Plus 租户使用一. 前言1.1 租户存在的意义1.2 租户框架 二. Mybatis-plus 租户2.1 租户处理器2.2 前置准备1. 依赖2. 表及数据准备3. 代码生成器 2.3 使用 三. 深入使用3.1 前言3.2 租户主体设值&#xff0c;取值3.3 部分表全量db操作3…...

vue el-table (固定列+滚动列)【横向滚动条】确定滚动条是在列头还是列尾

效果图&#xff1a; 代码实现&#xff1a; html&#xff1a; <script src"//unpkg.com/vue2/dist/vue.js"></script> <script src"//unpkg.com/element-ui2.15.14/lib/index.js"></script> <div id"app" style&quo…...

⑦【Redis GEO 】Redis常用数据类型:GEO [使用手册]

个人简介&#xff1a;Java领域新星创作者&#xff1b;阿里云技术博主、星级博主、专家博主&#xff1b;正在Java学习的路上摸爬滚打&#xff0c;记录学习的过程~ 个人主页&#xff1a;.29.的博客 学习社区&#xff1a;进去逛一逛~ Redis GEO ⑦Redis GEO 基本操作命令1.geoadd …...

LeetCode 2304. 网格中的最小路径代价:DP

【LetMeFly】2304.网格中的最小路径代价&#xff1a;DP 力扣题目链接&#xff1a;https://leetcode.cn/problems/minimum-path-cost-in-a-grid/ 给你一个下标从 0 开始的整数矩阵 grid &#xff0c;矩阵大小为 m x n &#xff0c;由从 0 到 m * n - 1 的不同整数组成。你可以…...

c 实用化的文本终端实时显示摄像头视频

因为采用yuv格式&#xff0c;帧率都很低。图像会拖影。把图像尺寸尽量缩小&#xff0c;能大大改善。现在最麻烦的是图像上有黑色的闪影&#xff0c;不知是为啥&#xff1f;如是framebuffer引起的就无解了。终于找到问题了&#xff0c;是在显示前加了一条用黑色清屏造成的&#…...

CSS中常用的伪类选择器

一 、伪类&#xff08;不存在的类&#xff0c;特殊的类&#xff09; -伪类用来描述一个元素的特殊状态 比如&#xff1a;第一个元素&#xff0c;被点击的元素&#xff0c;鼠标移入的元素 -特点&#xff1a;一般请情况下&#xff0c;使用&#xff1a;开头 1、 :first-child …...

【python学习】中级篇-数据库操作:SQLite

SQLite是一个轻量级的数据库引擎&#xff0c;它可以嵌入到各种应用程序中。以下是SQLite的基本用法&#xff1a; 创建数据库文件 import sqlite3# 连接到一个不存在的数据库文件&#xff0c;如果文件不存在&#xff0c;将会自动创建一个新的数据库文件 conn sqlite3.connect…...

汇编-PROTO声明过程

64位汇编 64 模式中&#xff0c;PROTO 伪指令指定程序的外部过程&#xff0c;示例如下&#xff1a; ExitProcess PROTO ;指定外部过程&#xff0c;不需要参数.code main PROCmov ebx, 0FFFFFFFFh mov ecx,0 ;结束程序call ExitProcess ;调用外部过程main ENDP END 32位…...

MYSQL事务操作

...

自动化测试——自动卸载软件

&#x1f4e2;专注于分享软件测试干货内容&#xff0c;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1f4dd; 如有错误敬请指正&#xff01;&#x1f4e2;交流讨论&#xff1a;欢迎加入我们一起学习&#xff01;&#x1f4e2;资源分享&#xff1a;耗时200小时精选的「软件测试」资…...

未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?

编辑&#xff1a;陈萍萍的公主一点人工一点智能 未来机器人的大脑&#xff1a;如何用神经网络模拟器实现更智能的决策&#xff1f;RWM通过双自回归机制有效解决了复合误差、部分可观测性和随机动力学等关键挑战&#xff0c;在不依赖领域特定归纳偏见的条件下实现了卓越的预测准…...

iOS 26 携众系统重磅更新,但“苹果智能”仍与国行无缘

美国西海岸的夏天&#xff0c;再次被苹果点燃。一年一度的全球开发者大会 WWDC25 如期而至&#xff0c;这不仅是开发者的盛宴&#xff0c;更是全球数亿苹果用户翘首以盼的科技春晚。今年&#xff0c;苹果依旧为我们带来了全家桶式的系统更新&#xff0c;包括 iOS 26、iPadOS 26…...

线程与协程

1. 线程与协程 1.1. “函数调用级别”的切换、上下文切换 1. 函数调用级别的切换 “函数调用级别的切换”是指&#xff1a;像函数调用/返回一样轻量地完成任务切换。 举例说明&#xff1a; 当你在程序中写一个函数调用&#xff1a; funcA() 然后 funcA 执行完后返回&…...

镜像里切换为普通用户

如果你登录远程虚拟机默认就是 root 用户&#xff0c;但你不希望用 root 权限运行 ns-3&#xff08;这是对的&#xff0c;ns3 工具会拒绝 root&#xff09;&#xff0c;你可以按以下方法创建一个 非 root 用户账号 并切换到它运行 ns-3。 一次性解决方案&#xff1a;创建非 roo…...

学习STC51单片机31(芯片为STC89C52RCRC)OLED显示屏1

每日一言 生活的美好&#xff0c;总是藏在那些你咬牙坚持的日子里。 硬件&#xff1a;OLED 以后要用到OLED的时候找到这个文件 OLED的设备地址 SSD1306"SSD" 是品牌缩写&#xff0c;"1306" 是产品编号。 驱动 OLED 屏幕的 IIC 总线数据传输格式 示意图 …...

Caliper 配置文件解析:config.yaml

Caliper 是一个区块链性能基准测试工具,用于评估不同区块链平台的性能。下面我将详细解释你提供的 fisco-bcos.json 文件结构,并说明它与 config.yaml 文件的关系。 fisco-bcos.json 文件解析 这个文件是针对 FISCO-BCOS 区块链网络的 Caliper 配置文件,主要包含以下几个部…...

精益数据分析(97/126):邮件营销与用户参与度的关键指标优化指南

精益数据分析&#xff08;97/126&#xff09;&#xff1a;邮件营销与用户参与度的关键指标优化指南 在数字化营销时代&#xff0c;邮件列表效度、用户参与度和网站性能等指标往往决定着创业公司的增长成败。今天&#xff0c;我们将深入解析邮件打开率、网站可用性、页面参与时…...

20个超级好用的 CSS 动画库

分享 20 个最佳 CSS 动画库。 它们中的大多数将生成纯 CSS 代码&#xff0c;而不需要任何外部库。 1.Animate.css 一个开箱即用型的跨浏览器动画库&#xff0c;可供你在项目中使用。 2.Magic Animations CSS3 一组简单的动画&#xff0c;可以包含在你的网页或应用项目中。 3.An…...

Linux nano命令的基本使用

参考资料 GNU nanoを使いこなすnano基础 目录 一. 简介二. 文件打开2.1 普通方式打开文件2.2 只读方式打开文件 三. 文件查看3.1 打开文件时&#xff0c;显示行号3.2 翻页查看 四. 文件编辑4.1 Ctrl K 复制 和 Ctrl U 粘贴4.2 Alt/Esc U 撤回 五. 文件保存与退出5.1 Ctrl …...

Golang——6、指针和结构体

指针和结构体 1、指针1.1、指针地址和指针类型1.2、指针取值1.3、new和make 2、结构体2.1、type关键字的使用2.2、结构体的定义和初始化2.3、结构体方法和接收者2.4、给任意类型添加方法2.5、结构体的匿名字段2.6、嵌套结构体2.7、嵌套匿名结构体2.8、结构体的继承 3、结构体与…...