Rust 从入门到精通05-数据类型
Rust 是 静态类型(statically typed)语言,也就是说在编译时就必须知道所有变量的类型。
在 Rust 中,每一个值都属于某一个 数据类型(data type),分为两大类:
①、标量(scalar):整型、浮点型、布尔类型、字符类型
②、复合(compound):元祖(tuple)、数组(array)、结构体(struct)
1、标量scalar
每个类型有一个单独的值。
1.1 整型
表示没有小数部分的数字,分为有符号(以 i 开头)和无符号(以 u 开头)整型。
数字类型的默认类型是 i32。
| 长度 | 有符号 | 无符号 |
|---|---|---|
| 8-bit | i8 |
u8 |
| 16-bit | i16 |
u16 |
| 32-bit | i32 |
u32 |
| 64-bit | i64 |
u64 |
| 128-bit | i128 |
u128 |
| arch | isize |
usize |
每一个有符号的整型可以储存包含从 -(\(2^{n - 1}\)) 到 \(2^{n - 1}\) - 1 在内的数字,这里 n 是整型定义的长度。所以 i8 可以储存从 -\(2^7\)到 \(2^7\) - 1 在内的数字,也就是从 -128 到 127。无符号的变体可以储存从 0 到 \(2^{n - 1}\) 的数字,所以 u8 可以储存从 0 到 \(2^8 - 1\) 的数字,也就是从 0 到 255。
另外,isize 和 usize 类型依赖运行程序的计算机架构:64 位架构上它们是 64 位的, 32 位架构上它们是 32 位的。
1.1.1 所有数字字面量,可以在任意地方添加下划线_
fn int_test(){
//所有数字字面量,可以在任意地方添加下划线_
let x : u32 = 1_2_3;
let y = x + 1;
//打印结果为 124
println!("{}",y);
}
1.1.2 字面量可以跟类型后缀,表示数字具体类型
//字面量可以跟类型后缀,表示数字具体类型
fn int_test2(){
let x = 123i32;
let y = x + 1;
//打印结果为 124
println!("{}",y);
}
1.1.3 直接对整型字面量调用函数
//直接对整型字面量调用函数
fn int_test3(){
let x : i32 = 9;
//打印结果为 729
println!("9 power 3 = {}",x.pow(3));
}
1.1.4 整数溢出
Rust 对于整数溢出的处理方式如下:
①、默认情况下,在debug模式下编译器会自动插入整数溢出检查,一旦发生溢出,则会引发 panic;
②、在 release 模式下,不检查整数溢出,而是自动舍弃高位的方式。
1.1.5 如何选择
通常默认类型 i32 即可,它通常是最快的。
1.2 浮点
Rust 有两个原生的 浮点数(floating-point numbers)类型,它们是带小数点的数字。是基于 IEEE 754-2008 标准的浮点类型,分别是 f32 和 f64,分别占 32 位和 64 位。默认类型是 f64,因为在现代 CPU 中,它与 f32 速度几乎一样,不过精度更高。
fn float_test(){
//123.0 f32类型
let f1 = 123.0f32;
//0.1 f64类型
let f2 = 0.1f64;
}
1.3 布尔类型
布尔类型(bool)代表的是“是”和“否”的二值逻辑。它有两个值:
true和false
一般用在逻辑表达式中,可以执行“与”“或”“非”等运算。
fn bool_test(){
let x = true;
//取反运算
let y = !x;
//逻辑与,带短路功能
let z = x && y;
//逻辑或,带短路功能
let z = x || y;
}
1.4、字符类型
字符类型由 char 表示。它可以描述任何一个符合 unicode 标准的字符值。在代码中,单个的字符字面量用单引号包围(不同于字符串用):
1.4.1 4个字节字符
let heart_eyed_cat = '';
因为 char 类型的设计目的是描述任意一个 unicode 字符,因此它占据的内存空间不是1个字节,而是 4 个字节。
这意味着它可以比 ASCII 表示更多内容。在 Rust 中,拼音字母(Accented letters),中文、日文、韩文等字符,emoji(绘文字)以及零长度的空白字符都是有效的 char 值。Unicode 标量值包含从 U+0000 到 U+D7FF 和 U+E000 到 U+10FFFF 在内的值。
1.4.2 1个字节字符-u8
let x : u8 = 1;
对于 ASCII 字符其实只需要占据一个字节的空间,因此Rust 提供了单字节字符字面量来表示 ASCII 字符。
注意:我们还可以通过一个字母 b 在字符或者字符串前面,代表这个字面量存储在 u8 类型数组中,这样占用空间比 char 型数组要小一些。
let x : u8 = 1; let y : u8 = b'A';
2、复合compound
复合类型(Compound types)可以将多个值组合成一个类型
2.1 元祖(tuple)
①、由圆括号()包含一组表达式组成;
②、长度固定,一旦声明,其长度不会增大或缩小。
③、rust中可以存放不同类型的数据类型
2.1.2 实例
fn tuple_test1(){
//包含两个元素:1和false
let a = (1i32,false);
//包含两个元素:1和元祖,元祖包含两个字符1和2
let b = (1,("1","2"));
}
2.1.3 如果元祖只有一个元素,应该添加一个逗号,用来区分括号表达式和元祖
//如果元祖只有一个元素,应该添加一个逗号,用来区分括号表达式和元祖
fn tuple_test2(){
//a 是一个元祖,只有一个元素1
let a = (1,);
//b 是一个括号表达式,它是 i32类型
let b = (1);
}
2.1.4 访问元祖元素
①、模式匹配解构
//元祖:模式匹配
fn tup_test4(){
let tup = (1,1.1,2);
let (x,y,z) = tup;
println!("x={},y={},z={}",x,y,z);
}
②、数字索引
//元祖:数字索引
fn tup_test5(){
let tup = (1,1.1,2);
println!("x={},y={},z={}",tup.0,tup.1,tup.2);
}
2.2 数组(array)
①、由中括号[] 包含一组表达式组成;
②、数组中每个元素的类型必须相同(元祖tuple可以不同);
③、长度固定,一旦声明,其长度不会增大或缩小。
2.2.1 实例
有三种方式声明。
//数组:实例
fn array_test1(){
//1、省略类型和长度
let a = [1,1,1,1];
//2、声明类型和长度
let b:[i32;4] = [1,1,1,1];
//3、声明初始值和长度
let c = [1;4];
println!("{}",a == b);//true
println!("{}",a == c);//true
println!("{}",c == b);//true
}
2.2.2 访问数组元素
①、通过下标访问
初始下标是0
//数组:访问元素
fn array_test2(){
let a = [1,2,3,4];
println!("a[0]={}",a[0]);
println!("a[1]={}",a[1]);
println!("a[2]={}",a[2]);
}
②、通过 get() 方法
注意返回值是 Option
//数组:访问元素
fn array_test3(){
let a = [1,2,3,4];
let first = a.get(0);
let last = a.get(4);
println!("{:?}",first);//Some(1)
println!("{:?}",last);//None
}
2.2.3 数组越界访问异常
如果声明的数组有4个,但是访问下标大于或等于4,则会在运行时抛出异常(编译能过)。
//数组:访问元素
fn array_test3(){
let a = [1,2,3,4];
println!("a[4]={}",a[4]);
}

2.2.4 避免数组越界程序崩溃
如果我们不确定读取数组的索引是否合法,上面通过索引的方式访问就会发生异常,导致程序奔溃。
为了避免这种情况,我们可以使用 get(index) 的方法来获取数组中的元素,其返回值是 Option
//数组:访问元素
fn array_test3(){
let a = [1,2,3,4];
let first = a.get(0);
let last = a.get(4);
println!("{:?}",first);//Some(1)
println!("{:?}",last);//None
}
2.3 结构体(struct)
结构体和元祖类似,都可以把多个类型组合到一起,作为新的类型。
结构体又可以分为三种具体类型:
// 具名结构体
struct Name_Struct {
x : f32,
y : f32,
}
// 元祖结构体
struct Tuple_Struct(f32,f32);
// 单元结构体
struct Unit_Struct;
2.3.1 具名结构体
//结构体
fn struct_test1(){
struct Point{
x : i32,
y : i32,
}
let p = Point{x:0,y:0};
println!("{},{}",p.x,p.y);
}
①、每个元素之间采用逗号分开,最后一个逗号可以省略不写。
②、类型依旧跟在冒号后面,但是不能使用自动类型推导功能,必须显示指定。
局部变量和结构体变量一致,可以省略掉重复的冒号初始化
//局部变量和结构体变量一致,可以省略掉重复的冒号初始化
fn struct_test2(){
struct Point{
x : i32,
y : i32,
}
let x = 10;
let y = 20;
let p = Point{x,y};
println!("{},{}",p.x,p.y);
}
2.3.2 元祖结构体tuple struct
这是前面介绍的 tuple 和 struct 两种类型的混合,tuple struct 结构有名字,但是成员没有名字。
名字加圆括号,类型有单独的名字,成员没有单独的名字。
fn tuple_struct(){
struct Color (
i32,
i32,
i32
);
}
访问方法
通过下标访问:
fn tuple_struct(){
struct Color (
i32,
i32,
i32
);
let v1 = Color(1,2,3);
println!("{},{},{}",v1.0,v1.1,v1.2)
}
2.3.3 单元结构体
// 单元结构体
struct Unit_Struct;
单元结构体不会占用任何内存空间。
3、枚举 enum
如果说 tuple、struct、tuple struct 在 Rust 中代表的是多个类型的“与”关系,那么 enurn类型在 Rust 中代表的就是多个类型的“或”关系。
Rust 的 enurn 中的每个元素的定义语法与 struct 的定义语法类似。可以像空结构体一样,不指定它的类型;也可以像 tuple struct 一样,用圆括号加无名成员;还可以像正常结构体一样,用大括号加带名字的成员。
fn main() {
let x = enum_define::Int(12);
let y = enum_define::Float(3.2);
let z = enum_define::Move {x:1,y:2};
let k = enum_define::Color(255,255,255);
match x {
enum_define::Int(i) => {
println!("{}",i);
},
enum_define::Float(f) => {
println!("{}",f);
},
enum_define::Move{x,y} => {
println!("{} {}",x,y);
},
enum_define::Color(x,y,z) => {
println!("{}{}{}",x,y,z);
}
}
}
enum enum_define{
Int(i32),
Float(f32),
Move{x:i32,y:i32},
Color(i32,i32,i32),
}
4、特殊数据类型
4.1 Never 类型
表示不可能返回值的数据类型。
①、类型理论中,叫做底类型,底类型不包含任何值,但它可以合一到任何其它类型;
②、Never 类型用感叹号“!" 表示;
③、目前还未稳定,但是rust内部已经开始用了。
5、常见错误
5.1 类型转换必须通过 as 关键字显式声明
//类型转换必须通过 as 关键字显式声明
fn switch_test(){
let var1 : i8 = 1;
let var2 : i32 = var1;
}
报错如下:

增加 as 关键字显示声明即可。
//类型转换必须通过 as 关键字显式声明
fn switch_test(){
let var1 : i8 = 1;
let var2 : i32 = var1 as i32;
}
5.2 复合数据类型允许递归,但是不允许直接嵌套
//复合数据类型不允许直接嵌套
fn recursive(){
struct recur {
data : i32,
rec : recur
}
}
报错如下:

Rust 从入门到精通05-数据类型的更多相关文章
- 【MySQL】从入门到精通6-MySQL数据类型与官方文档
上期:[MySQL]从入门到精通5-一对多-外键 这个是官方文档链接,是世界上最全面的MySQL教学了,所有问题都可以在这里找到解决方法. https://dev.mysql.com/doc/ htt ...
- Rust 从入门到精通06-语句和表达式
1.语句和表达式 语句和表达式是 Rust 语言实现逻辑控制的基本单元. 在 Rust 程序里面,语句(Statement)是执行一些操作但不返回的指令,表达式(Expressions)计算并产生一个 ...
- Rust 从入门到精通01-简介
1.rust 从哪里来 Rust语言在2006年作为 Mozilla 员工 Graydon Hoare 的私人项目出现,而 Mozilla 于 2009 年开始赞助这个项目.第一个有版本号的 Rust ...
- Rust 从入门到精通03-helloworld
安装完成 Rust 之后,我们可以编写 Rust 的 Hello Word.这里介绍两种方式,一种是rust原生方式,一种是利用 cargo 工具(重要) 1.rustc 方式 1.1 创建项目目录 ...
- 【MySQL】从入门到精通7-设计多对多数据库
上期:[MySQL]从入门到精通6-MySQL数据类型与官方文档 第一章:理解 和一对多不一样,多对多意思是,一个数据可以被不同的数据关联. 如果是一对多,我们还可以用外键来达成. 但是现在我们是多对 ...
- Simulink仿真入门到精通(十九) 总结回顾&自我练习
从2019年12月27到2020年2月12日,学习了Simulink仿真及代码生成技术入门到精通,历时17天. 学习的比较粗糙,有一些地方还没理解透彻,全书梳理总结: Simulink的基础模块已基本 ...
- Web jquery表格组件 JQGrid 的使用 - 从入门到精通 开篇及索引
因为内容比较多,所以每篇讲解一些内容,最后会放出全部代码,可以参考.操作中总会遇到各式各样的问题,个人对部分问题的研究在最后一篇 问题研究 里.欢迎大家探讨学习. 代码都经过个人测试,但仍可能有各种未 ...
- 1、ASP.NET MVC入门到精通——新语法
本系列目录:ASP.NET MVC4入门到精通系列目录汇总 在学习ASP.NET MVC之前,有必要先了解一下C#3.0所带来的新的语法特性,这一点尤为重要,因为在MVC项目中我们利用C#3.0的新特 ...
- 5、ASP.NET MVC入门到精通——NHibernate代码映射
本系列目录:ASP.NET MVC4入门到精通系列目录汇总 上一篇NHibernate学习笔记—使用 NHibernate构建一个ASP.NET MVC应用程序 使用的是xml进行orm映射,那么这一 ...
随机推荐
- Linux详解(基础、环境配置、项目部署入门)
Linux(CentOS 7)操作系统 消息队列(Kafka.RabbitMQ.RocketMQ),缓存(Redis),搜索引擎(ES),集群分布式(需要购买多台服务器,如果没有服务器我们就只能使用虚 ...
- 什么事JAVA
1.什么是Java Java是一门面向对象的高级编程语言,不仅吸收了C++语言的各种优点,比如继承了C++语言面向对象的 技术核心.还摒弃了C++里难以理解的多继承.指针等概念,,同时也增加了垃圾回收 ...
- PostMan 快快走开, ApiFox 来了, ApiFox 强大的Api调用工具
简介 为什么要用ApiFox呢, 一般现在程序员开发测试, 一般都是PostMan, PostWoman等Api调用工具, 我之前也是一直在用, 但是今天我发现了一款相比于Postman更加好用的工具 ...
- GDKOI 2021 Day1 PJ 爆炸记
早上睡到 7:10 分才想起今天有 GDKOI ,赶紧去买了一个面包赶去机房 发现隔壁的大奆都过来了.比赛时由于昨晚一直没睡好,打了两个小时的哈欠 T1 :暴力模拟 根据 \(r\) 和 \(c\) ...
- 一张图进阶 RocketMQ - NameServer
前言 「三此君看了好几本书,看了很多遍源码整理的 一张图进阶 RocketMQ 图片链接,关于 RocketMQ 你只需要记住这张图!觉得不错的话,记得点赞关注哦.」 一张图进阶 RocketMQ 图 ...
- SAP Web Dynpro-使用服务调用
创建服务调用后,功能模块可用于组件. 现在可以选择一个视图,以便在浏览器中显示数据库表的元素. 如果全局控制器不是组件控制器,则必须为所选视图的控制器输入全局控制器的使用页面. 之后,应该有该节点的映 ...
- UiPath选择器之动态选择器的介绍和使用
一.动态选择器的介绍 使用通配符, 能够替换字符串中的零个或多个字符的符号.这些在处理选择器中的动态更改的属性时非常有用. 二.动态选择器在UiPath中的使用 1.在设计库中新建一个Sequence ...
- Java开发学习(六)----DI依赖注入之setter及构造器注入解析
一.DI依赖注入 首先来介绍下Spring中有哪些注入方式? 我们先来思考 向一个类中传递数据的方式有几种? 普通方法(set方法) 构造方法 依赖注入描述了在容器中建立bean与bean之间的依赖关 ...
- ssh-配置及使用
ssh配置文件 SSH的配置文件在/etc/ssh/目录下 openssh-client安装后,生成的配置文件为ssh_config,主要用于连接其他linux主机时,加载此文件 op ...
- org/apache/poi/POIXMLTypeLoader或者java.lang.NoSuchFieldError: RETURN_NULL_AND_BLANK
原因是之前我的poi和ooxml版本有点低, 解决方案 将两者版本提高,我是将两者的版本都提高到了3.15