Rust的数据类型

news2024/9/26 1:29:08

【图书介绍】《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类型的变量n

    println!("{: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,32767

1000000000000000,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 -> Integer

println!("{}", '我' as i32);              // 25105=0x6211

println!("{}", '是' as u16);              // 26159=0x662f

println!("{}", '是' as u8);                // 47=0x2f,被截断了,因此66就没输出

}

结果输出:

25105

26159

47

我们以十进制形式输出了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;                 // 默认f64

    let y: f32 = 3.14;            // f32

    let z:f64=6.28;                //f64

    println!("{},{},{}",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));

}

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

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

相关文章

使用html+css+layui实现动态表格组件

1、概述 需求,表格第一列指标可配置通过后端api传进来,表格显示数据以及鼠标触摸后气泡弹出层提示信息都是从后端传过来,实现动态表格的组件!!实现效果如下: 接口标准数据格式如下: {"data": {"date": ["8.20","8.21","…

Cmd终端

组策略停止更新 windows用户的分类 system&#xff08;系统用户&#xff09; administrator&#xff08;管理员用户&#xff09; 普通用户 访客用户 网络管理类命令练习 ping&#xff1a;用于测试网络连接是否正常。通过发送ICMP&#xff08;Internet Control Message Protoco…

力扣 | 递归 | 区间上的动态规划 | 486. 预测赢家

文章目录 一、递归二、区间动态规划 LeetCode&#xff1a;486. 预测赢家 一、递归 注意到本题数据范围为 1 < n < 20 1<n<20 1<n<20&#xff0c;因此可以使用递归枚举选择方式&#xff0c;时间复杂度为 2 20 1024 ∗ 1024 1048576 1.05 1 0 6 2^{20…

Linux--目录与文件操作函数

一、目录和&#xff08;硬&#xff09;链接 可在 shell 中利用 ln 命令为一个业已存在的文件创建新的硬链接 添加图片注释&#xff0c;不超过 140 字&#xff08;可选&#xff09; 2. 同一文件的所有名字&#xff08;链接&#xff09;地位平等—没有一个名字&#xff08;比如…

计应8-01-作业1-静态网页

IP C:\Users\WL>ipconfig // win 查看 ip Windows IP 配置以太网适配器 以太网: //连接特定的 DNS 后缀 . . . . . . . :本地链接 IPv6 地址. . . . . . . . : fe80::6c95:9da6:140c:c59e%13IPv4 地址 . . . . . . . . . . . . : 192.168.51.243//子网掩码 . . . .…

mysql阿拉伯数字转换中文数字函数

函数如下 1.中间一部分代码可以提取出来作为公共方法&#xff0c;我这里并没有提取&#xff0c;因为我是在代码中动态添加的 2.样式目前只做了&#xff1a;123转为一百二十三这类的 drop function if EXISTS zz_convert_number_chinese; create FUNCTION zz_convert_number_…

ELK系列之四---如何通过Filebeat和Logstash优化K8S集群的日志收集和展示

前 言 上一篇文章《日志不再乱: 如何使用Logstash进行高效日志收集与存储》介绍了使用ELK收集通用应用的日志&#xff0c;在目前大多应用都已运行在K8S集群上的环境&#xff0c;需要考虑怎么收集K8S上的日志&#xff0c;本篇就介绍一下如何使用现有的ELK平台收集K8S集群上POD的…

新型供应链攻击手法 — “Revival Hijack”

JFrog 的网络安全研究人员发现了一种名为“Revival Hijack”的新型 PyPI 攻击技术&#xff0c;该技术利用包删除策略绕过安全检查。据统计&#xff0c;超过 22,000 个程序包处于风险之中&#xff0c;可能会影响数十万名用户。 JFrog 的网络安全研究人员发现了一种用于攻击 Pyth…

易灵思时钟输出问题记录

在添加 GPIO时&#xff0c;设置Mode为clkout,并在output Clock中输入时钟名。 这里需要 注意的是&#xff0c; 1. 时钟名不能从core直接输出&#xff0c;而只能使用interface中使用的时钟&#xff0c;如PLL输出的时钟或者GCLK输入的时钟。 2. 易灵思输出时钟不能做其他用途&a…

2024中国产业园区运营商50强榜单揭晓:行业洗牌加速,数智化是关键!

近日&#xff0c;备受瞩目的“2024年度中国产业园区运营商50强”榜单正式揭晓&#xff0c;不仅照亮了行业内的领军之星&#xff0c;更为我们揭示了产业园区运营管理平台在推动经济转型升级中的关键力量与未来趋势的璀璨图景。 从以上产业园区运营商 50 强的角度来看&#xff0…

30岁程序员的焦虑:转行还是继续死磕?现在什么方向更有前景?

最适合转入AI大模型的莫过于程序员和在读大学生了吧。 对于程序员来说&#xff0c;码农之路并不是一帆风顺。对于每一个入行IT业的社会青年来说&#xff0c;谁不是抱着想要成为最高峰的技术大咖或者跃进管理岗的小目标&#xff1f; 然而往往更多的人并非互联网吹捧的如此耀眼…

云原生技术:‌引领数字化转型的新浪潮

云原生技术&#xff1a;‌引领数字化转型的新浪潮 在数字化转型的时代背景下&#xff0c;‌企业面临着前所未有的挑战与机遇。‌随着云计算技术的飞速发展&#xff0c;‌云原生技术作为一种新型的应用程序开发和部署方式&#xff0c;‌正逐步成为构建高可用、‌可扩展应用程序…

MySQL复习1

基本概念 OLTP OLTP&#xff08;On-Line transaction processing&#xff09;翻译为联机事物处理&#xff1b;主要对数据库增删改查。 OLTP 主要用来记录某类业务事件的发生&#xff1b;数据会以增删改查的方式在数据库中更新处理操作&#xff0c;要求实施性强&#xff0c;稳…

OS_程序的装入与链接

2024.09.05&#xff1a;操作系统程序的装入与链接学习笔记 第12节 程序的装入与链接 2.1 程序的装入2.1.1 绝对装入方式2.1.2 可重定位装入方式&#xff08;静态重定位&#xff09;2.1.3 动态运行时装入方式&#xff08;动态重定位&#xff09; 2.2 程序的链接2.2.1 静态链接方…

LIN总线CAPL函数—— 检查LIN报头的时间(ChkStart_LINHeaderToleranceViolation

&#x1f345; 我是蚂蚁小兵&#xff0c;专注于车载诊断领域&#xff0c;尤其擅长于对CANoe工具的使用&#x1f345; 寻找组织 &#xff0c;答疑解惑&#xff0c;摸鱼聊天&#xff0c;博客源码&#xff0c;点击加入&#x1f449;【相亲相爱一家人】&#x1f345; 玩转CANoe&…

高级算法设计与分析 学习笔记3 哈希表

首先我们要讨论一个把n个数据放到列表S里面的问题&#xff1a; 但很显然&#xff0c;这些数据的范围有多大这个T就得有多大&#xff0c;而实际上要放的数字可能就几个&#xff08;比如就放一个1和一个10000000&#xff0c;那我还是要准备一个巨大的T&#xff09;&#xff0c;不…

【STM32】cubemx配置GPIO

直接使用STM32CubeMX点灯 使用之前的工程 配置GPIO 对四个灯设置GPIO输出 close后直接打开keil 演示

基于LangChain+LLM的相关技术研究及初步实践

0 1 概述 大模型概述 大模型是指具有大规模参数和复杂计算结构的机器学习模型。这些模型通常由深度神经网络构建而成&#xff0c;拥有数十亿甚至数千亿个参数。大模型的设计目的是为了提高模型的表达能力和预测性能&#xff0c;能够处理更加复杂的任务和数据。大模型在各种领…

提高 Facebook 参与度的 8个技巧

在社交媒体中&#xff0c;Facebook仍然是企业与受众建立联系的重要渠道。无论你是刚刚建立 Facebook 业务主页&#xff0c;还是经验丰富的营销人员&#xff0c;都必须了解人们如何跟你的主页互动。 一、什么是 Facebook 参与度&#xff1f; Facebook的参与度是指用户对你的 F…

潜望长焦+快充:vivo X200系列,小尺寸手机的大突破

在智能手机市场日益激烈的竞争中&#xff0c;厂商们不断推陈出新&#xff0c;以满足消费者多样化的需求。vivo作为中国知名的智能手机品牌&#xff0c;一直以其创新的设计和强大的功能赢得市场的认可。 近日&#xff0c;vivo X200系列的即将发布引起了广泛关注&#xff0c;特别…