Rust的数据类型
【图书介绍】《Rust编程与项目实战》-CSDN博客
《Rust编程与项目实战》(朱文伟,李建英)【摘要 书评 试读】- 京东图书 (jd.com)
Rust到底值不值得学,之一 -CSDN博客
Rust到底值不值得学,之二-CSDN博客
3.5 数据类型的定义和分类
在Rust编程中,所谓数据类型,就是对数据存储的安排,包括存储单元的长度(占多少字节)以及数据的存储形式。不同的数据类型分配不同的长度和存储形式。
在编程时,我们将变量存储在计算机的内存中,但是计算机要知道我们要用这些变量存储什么样的值,因为一个简单的数值,一个字符或一个巨大的数值在内存中所占用的空间是不一样的。
在Rust中,每个值都属于某一个数据类型,用来告诉Rust它被指定为何种数据,以便明确数据处理方式。Rust基本数据类型主要有两类子集:标量(Scalar)类型和复合(Compound)类型。标量类型是单个值类型的统称。Rust中内建了4种标量类型:整数、浮点数、布尔值及字符类型。复合类型包括数组、元组、结构体和枚举等。
这里所讲的基本数据类型都是Rust原生的数据类型,它们都是创建在栈上的数据结构。Rust 标准库还提供了一些更复杂的数据类型,它们有些是创建在堆上的数据结构,这里先不讲。
Rust是静态类型语言,因此在编译时就必须知道所有变量的类型。通常,根据值及其使用方式,Rust 编译器可以推断出我们想要用的类型,当多种类型均有可能时,必须增加类型注解,否则编译会报错。
3.6 标量数据类型
3.6.1 整型
整型也叫整数类型,是专门用来定义整数变量的数据类型。按照整型变量占用的内存空间大小来讲,整型可以划分为 1字节整型、2字节整型、4字节整型、8字节整型、16字节整型。
按最高位是否当作符号位来讲,Rust 中的整型又分为有符号整型(Unsigned)和无符号整型(Signed)。有符号整型的左边最高位为0表示正数,为1则表示负数。有符号整型可以用来定义存储负数的变量,当然也可以定义存储非负数的变量。而无符号整型定义的变量只存储非负整数。
整型数据在内存中的存储方式:用整数的补码形式存放,原因在于,使用补码可以将符号位和数值域统一处理;同时,加法和减法也可以统一处理。一个整数X的补码计算方式可以用以下公式得到:
- 当X≥0时,X的补码=X的二进制形式。
- 当X < 0时,X的补码=(X + 2n)的二进制形式,n是补码的位数。
可以看出,一个非负整数的补码就是该数本身的二进制形式,负整数稍微复杂一些。
比如0,如果用1字节的存储单元存储一个整数,则其补码就是00000000,在内存中存储的形式就是00000000;又比如8,其二进制形式是1000,如果用1字节的存储单元存储一个整数,则在内存中的数据就是00001000。对于−8,假设用1字节的存储单元存储一个整数,根据公式,−8的补码就是(−8+28=−8+256=248)的二进制形式,即11111000,也就是它在内存中存放的形式。
1. 有符号的8位整型i8
有符号的8位整型的类型名是i8,为了方便,经常会省略有符号3个字,直接称8位整型,或超短整型。编译器分配1字节长度的存储单元给i8定义的变量,最高位是符号位,0表示正数,1表示负数。比如定义一个i8类型的变量n:
let n: i8 = -6;
这个变量n在内存中占据1字节的存储单元,其在内存中的补码位(−6+256=250)的二进制形式为11111010。如果不信,当场验证一下,代码如下:
fn main() {let n:i8=-6; //定义一个i8类型的变量nprintln!("{:b}",n); //:b的意思是以二进制形式输出变量n的值}
结果输出:11111010。
下面我们来看i8类型所能定义的数据的最小值和最大值,这个问题很多书都没讲清楚。i8类型整数的补码有8位,表示的范围为0000 0000~1111 1111,我们通过补码计算公式可以得到表3-2。
从表3-2中不难看出,最大值只能表示到127,因为128的补码最高位(符号位)是1,不能用来表示一个正数。而最小值是−128,因为−129的补码最高位(符号位)是0,不能用来表示一个负数。所以,我们得出i8类型所表示的最小值是−128,最大值是127。这里使用列表法得到最小值和最大值,似乎有点笨笨的。笔者再介绍一个更简便的方法得到最小值和最大值。
根据补码计算公式,非负数的二进制形式和补码相同,我们可以这样考虑来得到最大值,i8类型定义的变量所占用的存储空间长度是1字节,且最高位是符号位,则能存储的最大数据是01111111,左边第一位是0表示正数,后面7位表示数值,7位全为1时最大,因此最大数据就是27−1=127。对于最小值,则根据负数的补码计算公式,我们知道,正整数的补码是其本身的二进制数,负整数的补码就是(X + 2n)的二进制数,现在,0~127的二进制数已经用作正整数的补码了,那么一个负整数X的补码只能从128的二进制数开始找,也就是有这样的关系:X+256≥128,即X≥−128,从而得出最小值Xmin=−128。这个方法方便多了。如果不信,当场验证一下,代码 如下:
fn main() {assert_eq!(i8::MIN, -128); assert_eq!(i8::MAX, 127); println!("{},{}",i8::MIN,i8::MAX);}
结果输出就是−128,127。其中,Rust提供了i8::MIN来表示i8变量的最小值(−128),用i8::MAX表示i8变量的最大值(127)。而assert_eq!表示传入的两个参数如果不相等,则抛出异常,也就是会在输出窗口打印一行语句:thread 'main' panicked at 'assertion failed: `(left == right)`。
2. 无符号8位整型u8
无符号8位整型的类型名是u8,又称无符号超短整型,它占据1字节长度的存储单元,最高位不是符号位。这里的u表示unsigned,u8定义的变量取值是非负整数,存储形式依旧是补码,根据补码计算公式,非负整数的补码和变量本身的二进制形式相同,比如变量值是255,那么其在内存中的存储形式就是11111111,它就是补码,也是255的二进制形式。
定义一个u8变量示例如下:
let n: u8 = 100;
u8的最高位不是符号位,是有效的数值位,因此u8定义的变量,其最小值是0,最大值是11111111,即28−1=255,我们可以用下列代码来验证:
fn main() {println!("{},{}",u8::MIN,u8::MAX);}
输出结果:0,255。
3. 有符号16位整型i16
有符号16位整型的类型名是i16,占据2字节长度的存储单元,最高位是符号位。i16有时又称为短整型。定义一个i16变量示例如下:
let n: i16 = -100;
i16的最高位是符号位,若为0则表示正数,若为1则表示负数。i16定义的变量,其最大值是0111111111111111,即215−1=32767,最小值这样计算:X+65536≥32768,即X≥−32768,从而得出最小值Xmin=−32768,对应补码为(−32768+65536)的二进制形式,即32768的二进制数 1 000 000 000 000 000。得到最小值和最大值的原理这里不再赘述,因为已经在讲i8的时候详述过了。我们可以用下列代码来验证:
fn main() {println!("{},{}",i16::MIN,i16::MAX);println!("{:b},{:b}",i16::MIN,i16::MAX);}
运行结果如下:
-32768,327671000000000000000,111111111111111
4. 无符号16位整型u16
无符号16位整型的类型名是u16,占据2字节长度的存储单元,最高位不是符号位。u16有时又称无符号短整型。定义一个u16变量示例如下:
let n: u16 = 100;
u16定义的变量取值范围是[0, 65535]。
5. 32位、64位、128位整型
一理通百理融。了解了8位、16位整型后,32位、64位、128位整型与之类似。i32是默认的整型,如果直接说出一个数字而不说它的数据类型,那么它默认就是i32。i64通常称为长整型,i128称为超长整型。
我们可以用一张表来归纳这些整型,Rust内建的整数类型如表3-3所示。
整型的长度还可以是arch。arch是由CPU构架决定大小的整型类型。大小为arch的整数在x86机器上为32位,在x64机器上为64位。arch整型通常用于表示容器的大小或者数组的大小,或者数据在内存上存储的位置。
有符号整型所表示的范围如表3-4所示。
无符号整型所表示的范围如表3-5所示。
3.6.2 布尔型
Rust使用关键字bool表示布尔数据类型,布尔型变量共有两个值:true和false。比如定义一个bool变量:
let checked:bool = true;
布尔变量占用1字节,使用bool类型的场景主要是条件判断。下列代码将输出bool变量的值:
fn main() {let checked:bool = true;println!("{}", checked);//输出true}
输出结果:true。
3.6.3 字符类型
字符类型是Rust的一种基本数据类型,使用关键字char来表示字符类型。字符类型变量用于存放单个Unicode字符,这意味着ASCII字母、重音字母、中文、日文、韩文、表情符号和零宽度空格都是Rust中的有效字符值。Unicode 标量值的范围为U+0000~U+D7FF和U+E000~U+10FFFF(含)。然而,“字符”在Unicode中并不是一个真正的概念。在存储char类型数据时,会将其转换为UTF-8编码的数据(即Unicode代码点)进行存储。
char定义变量占用4字节空间(32bit),且不依赖于机器架构。我们可以用代码验证一下:
fn main() {println!("{}", std::mem::size_of::<char>());}
结果输出:4。看来的确占用了4字节。std是Rust的标准库,mem是std中的一个模块,size_of是模块mem中的函数,它返回某种数据类型占用的字节数。关于库、模块和函数的概念后面详述,现在只要知道这样调用是可以得到某个类型所占用的字节数的。
char类型变量的值是单引号包围的任意单个字符,例如'a'、'我'。注意:char和单字符的字符串String是不同的类型。比如下列代码定义字符类型变量并输出:
fn main() {let a = 'z';let b = '\n'; //赋值转义字符'\n'let c = '我';print!("{},{},{}",a,b,c); //输出}
输出结果:
z,,我
b的值是'\n',因此会出现换行。
另外,可使用关键字as将char转为各种整数类型,目标类型小于4字节时,将从高位截断,这种转换叫作显式转换。注意:Rust不会自动将char类型转换为其他类型,必须使用as进行显式转换。比如:
fn main() {// char -> Integerprintln!("{}", '我' as i32); // 25105=0x6211println!("{}", '是' as u16); // 26159=0x662fprintln!("{}", '是' as u8); // 47=0x2f,被截断了,因此66就没输出}
结果输出:
251052615947
我们以十进制形式输出了3个字符的Unicode值,第三行中的'是'转为u8类型,只能把0x2f存于u8中,66就被截断了。如果想在线查询某个字符的Unicode编码值,可以到网站https://www.unicodery.com上查询。
关于整型转为char类型,将用到标注库的char模块,我们到讲标准库的时候再讲。
3.6.4 浮点型
浮点型变量用来表示具有小数点的实数。为何在Rust中把实数称为浮点数呢?这是因为在Rust中,实数是以指数形式存放在存储单元中的。一个实数表示为指数可以有多种形式,比如5.1234可以表示为5.1234×100、51.234×10-1、0.51234×101、0.051234×102、51234×10-5、512340×10-6等。可以看到,小数点的位置可以在5、1、2、3、4这几个数字之间、之前或之后(需添加0)浮动,只要在小数点位置浮动的同时改变指数的值,就可以保证表示的是同一个实数。因为小数点位置可以浮动,因此以指数形式表示的实数称为浮点数。Rust 编程语言按照 IEEE 754 二进制浮点数表示与算术标准存储浮点数。IEEE 754这里就不展开了,如果以后大家从事这方面的底层开发,可以深入研读这个标准。这里只是让大家心里有个数。
与大多数编程语言一样,Rust也拥有两种不同精度的浮点类型,分为单精度浮点类型f32和双精度浮点类型f64。f32的数据使用32位来表示,f64的数据使用64位来表示。Rust中的默认浮点类型是f64,因为现在的CPU几乎为64位的,因此在处理f64和f32类型的数据时所耗的时间基本相同,但f64可表示的精度更高。值得注意的是,所有的浮点类型都是有符号的。下列代码输出3个浮点类型变量:
fn main() {let x = 2.01; // 默认f64let y: f32 = 3.14; // f32let z:f64=6.28; //f64println!("{},{},{}",x,y,z);}
结果输出:2.01,3.14,6.28。
值得注意的是,Rust中不能将0.0赋值给任意一个整型,也不能将0赋值给任意一个浮点型,但可以将0.0赋值给浮点类型变量。
当数字很大的时候,Rust可以用下画线(_)来分段数字,这样可以使数字的可读性变得更好。比如:
fn main() {let a=1_000_000;let b:i64 =1_000_00088000;let x:f64=1_000_000.666_123;println!("{},{},{}",a,b,x);}
结果输出:1000000,100000088000,1000000.666123。
3.6.5 得到变量的字节数
我们可以用std::mem::size_of::<类型>得到类型所占的字节数,比如:
println!("{}", std::mem::size_of::<char>());
输出结果是4。
除此之外,还可以通过std::mem::size_of_val获取变量所占用的字节数。比如:
fn main() {//明确指定类型let a:i64=100;// 通过变量类型后缀指定变量的类型let x = 1u8;let y = 2u32;let z = 3f32;// 没有变量类型后缀,通过怎么使用变量来进行推断let i = 1;let f = 1.0;println!("size of `a` in bytes: {}", std::mem::size_of_val(&a));println!("size of `x` in bytes: {}", std::mem::size_of_val(&x));println!("size of `y` in bytes: {}", std::mem::size_of_val(&y));println!("size of `z` in bytes: {}", std::mem::size_of_val(&z));println!("size of `i` in bytes: {}", std::mem::size_of_val(&i));println!("size of `f` in bytes: {}", std::mem::size_of_val(&f));}
相关文章:

Rust的数据类型
【图书介绍】《Rust编程与项目实战》-CSDN博客 《Rust编程与项目实战》(朱文伟,李建英)【摘要 书评 试读】- 京东图书 (jd.com) Rust到底值不值得学,之一 -CSDN博客 Rust到底值不值得学,之二-CSDN博客 3.5 数据类型的定义和分类 在Rust…...

如何在vim中批量注释和取消注释
一、批量注释 首先在你需要注释的初始所在行在命令模式下输入CTRL v,然后按下HJKL来控制方向(不能使用键盘上的箭头方向键): 然后输入 shifti: 输入两个斜杠然后加exc就可以完成批量注释: 二、批量取消注…...

Centos7.9 安装Elasticsearch 8.15.1(图文教程)
本章教程,主要记录在Centos7.9 安装Elasticsearch 8.15.1的整个安装过程。 一、下载安装包 下载地址: https://www.elastic.co/cn/downloads/past-releases/elasticsearch-8-15-1 你可以通过手动下载然后上传到服务器,也可以直接使用在线下载的方式。 wget https://artifacts…...

哈希表-数据结构
一、哈希表基本概念 哈希表(也称为散列表)是根据键而直接访问在内存存储位置的数据结构,也就是说实际上是经过哈希函数进行映射,映射道表中一个位置来访问记录,这个存放记录的数组称为散列表。 哈希函数:就…...

指针之旅(4)—— 指针与函数:函数指针、转移表、回调函数
目录 1. 函数名的理解 1.1 “函数名”和“&函数名”的含义 1.2 函数(名)的数据类型 2. 函数指针(变量) 2.1 函数指针(变量)的创建格式 2.2 函数指针(变量)的使用格式 2.3 例子 判别 3. typedef 关键字 3.1 typedef的作用 3.2 typedef的运作逻辑 和 函数指针类型…...

打造线上+线下相结合的O2O平台预约上门服务小程序源码系统 带完整的安装代码包以及搭建部署教程
系统概述 本系统采用前后端分离的设计架构,前端以微信小程序为载体,提供直观、易用的用户界面;后端则采用稳定的服务器架构,确保数据处理的高效与安全。系统主要包括用户端、商户端和管理员端三大模块,通过API接口实现…...

python sys模块
在Python中,sys模块提供了访问和使用解释器的许多功能的方法,包括命令行参数、环境变量、路径管理、标准输入输出流等。sys模块是Python的标准库的一部分,不需要额外安装即可使用。 常用的sys模块功能 1. sys.argv sys.argv是一个包含命令…...

【Linux 报错】SSH服务器拒绝了密码。请再试一次。(xshell)
出现该错误 可能的原因: 你写入的登录密码错误了,错误原因有: 1、本来输入就错误了 2、创建用户时,只创建了用户名,但密码没有重新设置 3、多人使用同一台服务器时,该服务器管理员(本体&#x…...

云计算实训43——部署k8s基础环境、配置内核模块、基本组件安装
一、前期系统环境准备 1、关闭防火墙与selinux [rootk8s-master ~]# systemctl stop firewalld[rootk8s-master ~]# systemctl disable firewalldRemoved symlink /etc/systemd/system/multi-user.target.wants/firewalld.service. Removed symlink /etc/systemd/system/dbus…...

TAbleau 可视化 干货分享 | 简单三步助你打造完美仪表板
只需单击几下,你将能轻松创建美观、信息丰富的可视化效果、节省时间并推动业务向前发展! 借助精心设计的仪表板,分析师可以更好地理解复杂数据背后的信息,更有效地向他人分享你的见解,从而做出更明智的决策。 值得思考…...

JVM性能调优之5种垃圾收集器
JDK垃圾收集器 一、Serial GC垃圾收集器Serial GC的工作原理Serial GC的特点Serial GC的配置参数Serial GC的适用场景Serial GC的优缺点优点:缺点: Serial GC的总结 二、Parallel GC垃圾收集器Parallel GC的工作原理Parallel GC的特点Parallel GC的配置参…...

基于单片机的仔猪喂饲系统设计
文章目录 前言资料获取设计介绍功能介绍设计清单具体实现截图参考文献设计获取 前言 💗博主介绍:✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计划导师,一名热衷于单片机技术探索与分享的博主、专注于 精通51/STM32/MSP430/AVR等单片机设…...

Helm Deploy Online Rancher v2.9.1
文章目录 准备安装查看下载 准备 $ kubectl get node NAME STATUS ROLES AGE VERSION kube-master01 Ready control-plane 19d v1.29.5 kube-node01 Ready <none> 19d v1.29.5 kube-node02 Ready <none&…...

【办公效率】Axure会议室预订小程序原型图,含PRD需求文档和竞品分析
作品说明 作品页数:共50页 兼容版本:Axure RP 8/9/10 应用领域:中小型企业的会议室在线预订 作品申明:页面内容仅用于功能演示,无实际功能 作品特色 本作品为会议室预订小程序原型图,定位于拥有中大型…...

论文解析一: SuperPoint 一种自监督网络框架,能够同时提取特征点的位置以及描述子
目录 SuperPoint:一种自监督网络框架,能够同时提取特征点的位置以及描述子1.特征点预训练2.自监督标签3.整体网络结构3.1 先对图像进行卷积3.2 特征点提取部分(Interest Point Decoder)3.3 特征描述子提取部分(Descrip…...

【评估指标】Fβ-score
1. Fβ-score 概述 Fβ-score 是一种综合考量精确率(precision)和召回率(recall)的分类评估指标。其公式为: 1.1 Precision(精确率):预测为正类的样本中,实际为正类的比…...

1963Springboot个性化音乐推荐管理系统idea开发mysql数据库web结构java编程计算机网页源码maven项目
博主介绍:专注于Java .net php phython 小程序 等诸多技术领域和毕业项目实战、企业信息化系统建设,从业十五余年开发设计教学工作 ☆☆☆ 精彩专栏推荐订阅☆☆☆☆☆不然下次找不到哟 我的博客空间发布了1000毕设题目 方便大家学习使用 感兴趣的可以…...

solidity从入门到精通(持续更新)
我一度觉得自己不知何时变成了一个浮躁的人,一度不想受外界干扰的我被干扰了,再无法平静的去看一本书,但我仍旧希望我能够克服这些,压抑着自己直到所有的冲动和奇怪的思想都无法再左右我行动。 自律会让你更加自律,放纵…...

UEFI入门(二):edk2项目编译流程
UEFI入门(二):edk2项目编译流程 一、编译构建流程:1. 安装依赖工具2. 初始化构建环境3. 配置工具链和目标4. 定义平台配置5. 构建并编译 二、uefi-tools编译edk2实践:1. 克隆EDK2 项目2. 构建并编译 参考文章ÿ…...

局域网一套键鼠控制两台电脑(台式机和笔记本)
服务端(有键盘和鼠标的电脑作为服务端) 下载软件 分享文件:BarrierSetup-2.3.3.exe 链接:https://pan.xunlei.com/s/VO66rAZkzxTxVm-0QRCJ33mMA1?pwd4jde# 配置服务端 一, 二, 客户端屏幕名称一定要和…...

最新Nessus2024.9.8版本主机漏洞扫描/探测工具下载Windows版
Nessus号称是世界上最流行的漏洞扫描程序,全世界有超过75000个组织在使用它。该工具提供完整的电脑漏洞扫描服务,并随时更新其漏洞数据库。Nessus不同于传统的漏洞扫描软件,Nessus可同时在本机或远端上遥控,进行系统的漏洞分析扫描…...

关于使用 @iconify/vue2图标库组件的离线使用
Iconify 是最通用的图标框架,将各种图标库的图标集中在这里的一个组件库,例如ant-design,element-ui等 网站地址如下 https://iconify.design/getting-started/ 1.安装依赖 这两个包提供了图标组件和离线图标数据的支持。 npm install iconify/vue2 i…...

pdfmake生成pdf的使用
实际项目中有时会有根据填写的表单数据或者其他格式的数据,将数据自动填充到pdf文件中根据固定模板生成pdf文件的需求 文章目录 利用pdfmake生成pdf文件1.下载安装pdfmake第三方包2.封装生成pdf文件的共用配置3.生成pdf文件的文件模板内容4.调用方法生成pdf 利用pdf…...

PLM系统有哪些品牌推荐?国内不错的PLM厂商有哪些?
在当今快速变化的商业环境中,产品生命周期管理PLM系统已成为企业技术创新和管理创新的重要工具。PLM系统涵盖了产品从概念设计到市场推出、使用维护直至最终报废的整个生命周期,通过整合与产品相关的所有信息,助力企业实现高效、协同的产品开…...

Linux网络:网络套接字-TCP回显服务器——多进程/线程池(生产者消费者模型)
1.多进程版本 这里选择创建子进程,让子进程再创建子进程。父进程等待子进程,子进程的子进程处理业务逻辑。因为子进程是直接退出,子进程的子进程变成孤儿进程被系统管理,所以父进程在等待的时候不是阻塞等待的,所以可…...

Redis 篇-深入了解基于 Redis 实现消息队列(比较基于 List 实现消息队列、基于 PubSub 发布订阅模型之间的区别)
🔥博客主页: 【小扳_-CSDN博客】 ❤感谢大家点赞👍收藏⭐评论✍ 文章目录 1.0 消息队列的认识 2.0 基于 List 实现消息队列 2.1 基于 List 实现消息队列的优缺点 3.0 基于 PubSub 实现消息队列 3.1 基于 PubSub 的消息队列优缺点 4.0 基于 St…...

python 学习一张图
python学习一张图,python的特点的是学的快,一段时间不用,忘记的也快,弄一张图及一些入门案例吧。 写一个简单的测试: #!/usr/bin/python # -*- coding: UTF-8 -*- import osdef add_num(a, b):return a bif __name__…...

通过Docker部署 MongoDB 服务器
今天我们将在三丰云的免费服务器上进行 MongoDB 的部署测试。这款不错的免费服务器提供了很好的性能,1核CPU、1G内存、10G硬盘和5M带宽,足以满足我们的基本需求。三丰云的服务稳定,操作简单,真是一个值得推荐的选择,特…...

无人机避障雷达技术详解
随着无人机技术的飞速发展,其应用领域已经从最初的军事领域扩展到商业、农业、建筑巡检、应急救援、物流运输等多个领域。在这些多样化的应用场景中,无人机的安全性和稳定性显得尤为重要。无人机避障技术作为保障无人机安全飞行的核心技术之一࿰…...

2009-2023年上市公司华证esg评级评分数据(年度+季度)(含细分项)
2009-2023年上市公司华证esg评级评分数据(年度季度)(含细分项) 1、时间:2009-2023年 2、来源:整理自wind 3、指标:证券代码、年份、证券简称、评级日期、综合评级、综合得分、E评级、E得分、…...