坏蛋Dan
知乎@坏蛋Dan
发布时间:2024.1.3

前言

上篇文章中我们学了rust的变量、变量的可变性(mutability)、常量以及shadowing。没看过可以看下

坏蛋Dan:rust基础学习--day4

今天我们接着往下学。


环境

还是昨天那个项目


定义变量类型

rust是一门静态强类型语言,所以任何的变量的类型都需要在编译时确定下来。

与它相反的则是动态弱类型。我们都熟悉的javascript就是,类型是在runtime的时候才确定的,边解析边执行。当然,有typescript[2]之后舒服一些。

你在写js代码的时候是否会经常头疼没有代码提示,比如变量类型、函数用法等?那就是因为jsruntime的时候才进行解析。

所以在rust中,变量需要定义类型。 当然,也不是说非得每个变量都得你去写个类型才行,这多累。rust在编译(compile)的时候会根据你的值(value)推测出你的变量是什么类型的,所以大部分情况下你是不需要去手动写类型的。

但是有的情况它是没法去确定的,还记得我们之前的学习过程中遇到的强制你声明变量类型的报错吗[3]

这是因为parse可以转换的类型不止一种,可能是num又或者是bool等,这是不符合预期的,所以这里会强制你设置变量的类型,这样runtime的时候才能知道要parse成什么。

定义变量类型很简单,和写typescript一样,只需在变量后等号前: xxx即可。


标量类型(scalar types)

可以简单的理解为js中的基础数据类型,比如number、boolean等,也就是简单的数据类型。

rust中有四种标量类型:integers、floating-point-numbers、Booleans、characters,也就是:整数类型、浮动类型也就是带有小数的数字类型、布尔类型以及字符类型。

integer types

整数类型,上面parse那行代码中用的i32即是一个整数类型。但如果你看过之前的文章,应该会看到另一个类型u32。实际上他俩都是表示的整数类型。

为什么一个整数有两种类型呢?因为在计算机中负数并不是我们现实生活中的负数,而是一个带符号(二进制最高位置为1)的“正数“。

i就是integer,可用来定义正负数,而u表示unsigned,表示无符号的,只能用来定义正数。32表示32位。 类似的还有如下

其中arch表示的是根据你操作系统来判断,比如64位的就是i64u64

integer范围是根据类型定义时的位数来变化的,带符号的正数类型可存储范围为-(2^n - 1)(2^n - 1) - 1 ,而无符号的只能存储0 - (2^n) - 1范围之间。

比如i8表示-128 ~ 127。而u8则是0 ~ 255

另外rust中还有一种有趣的写法,不用去定义类型,可以把类型放到value中,比如:

123u8 表示数据是123,是u8类型的整数。

另一个有趣的写法是利用下划线把一个数字写的更方便阅读,比如:

10_00010000是同一个效果,但是可阅读性高了很多。

另外还有一点需要注意,那就是溢出的情况[6]

开发模式下如果你的数字溢出,会直接崩溃。而生产环境不会,会变成超出的那个值。比如u8类型设置一个266数值,在开发模式下会报错,但是生产环境下会变成9。

最后,整数的默认类型是i32


floating-point-numbers types

浮动类型。

f32f64以及fsize三种浮动类型。

默认是f64,因为速度快精度高(双精度)。

然后没啥好说的了,该说的integer里面说的差不多了。


二元运算

数字用的最多的地方自然就是计算,rust中的几种运算和其它语言一致,所以这里简单的过一下即可。


boolean type

布尔类型

rust中布尔类型占位一个字节,用bool定义布尔变量

完了~


characters type

字符类型

顾名思义,只有是一个字符的时候才算是character

超了直接报错,另外如果需要设置字符类型得用单引号,不然默认被认为是&str字符串类型。

其它其实也没什么好说的了,和其它语言其实差不多,包含包括ASCII\多种语言字符`emoji`等。

不过需要注意点一点是范围在``U+0000toU+D7FF、U+E000toU+10FFFF`之间,如果不在这个范围内,那就很有可能是乱码。

其实字符并非是一个Unicode的概念,所以在代码中可能会和你的想法有出入[9]

需要我们留意的一点就是字符串和字符不是同一个东西,字符串有自己的类型,后面会说到,这里就先不说了。


复合类型(compound types)

标量类型就说完了,现在我们来看下复合类型。

他们的区分其实挺好区分,标量类型只有一种数据又或者是结构,而复合类型允许多个数据或者结构放在同一个变量中。

rust中有两种原始的复合类型:Arraytuple也就是数组和元组。

tuple

元组相信大家都不陌生了,可以用来存储各种类型的值,不过有个点需要注意就是元组的长度是固定的,无法在定义后新增或者删除元素之类的。

直接来看下例子

cargo run一下

是不是很像python的元组?

那么问题来了,要怎么获取其中一个元素。

有两种方式:

  1. 解构,相信在座的各位都不陌生了,es6+的方法。

但是挺蛋疼的是解构需要给出所有的变量才行,比如我只想解构第一个元素,这样是不行的。

  1. 基于下标

第一种方法有些麻烦,所以基本上都是用的下标获取这种方式。

元组下标从0开始。

元组的默认值是一个(),表示empty,他们叫他unit,表达式默认返回值就是一个unit,(impilcitly不明显滴)。


Array

数组相信大家都很熟悉了

不过比起在js中,rustarray被设定为只能包含同一种类型的元素,也就是数组里的元素都得是同个类型。 同样的,它的长度也得是固定的,也是不能新增或者移除元素。

来看下代码

定义元素类型

格式为type; len。毕竟类型得一样,长度不可变。

这里还有一种快捷初始化数组的方式

格式为[value; len]。等价于[3, 3, 3, 3, 3]

获取元素的方式和元组差不多

  1. 通过解构

同样是需要全部解构才行

  1. 通过下标,也是最常用的方式

不过这种方式有一个大问题,那就是数组越界。

数组越界

java中应该是有同样的概念,指的是使用的下标超出数组的长度从而引发的错误。在c/c++中是允许读取超出数组自身长度的,不过数据有没有问题就不是它们的事了。。。

为什么会有这种错误呢?

rust中,数组是基于stack也就是栈实现的,毕竟空间固定不允许拓展。而栈的空间是连续的,毕竟LIFO。而栈相邻的空间是不知道是啥的,所以这个时候下标超了数据就错了。

例子就不看了,直接看下报错。

什么情况下会有这种错误?

当下标是一个变量比如从stdin中获取的,这时就会有可能有问题,而且这个问题并不能在编译过程中发现,这是一个runtime error,因为你并不能确定用户输入了什么(客户在酒吧点了一份炒饭然后酒吧炸了~[14])。

如果想让数组变化的话可以用vector[15],由标准库提供,可改变数组长度等。官方也是很建议用这个vector,如果你不知道用哪个,优先vector

先来看下如何使用,具体分析后面会说到。

同样是要求元素类型一样,但是可以伸缩(误)。

新增元素和其他语言差不多,都是push,不过有个点需要注意就是数组自身得是mut的。


总结

今天我们学习了rust中的标量类型和原始复合类型。

感觉东西很少,但是就是有些累。。。可能是上班遇到了个蛇皮需求。。。

老规矩如果觉得对你有用麻烦点个赞,谢谢~

参考

  1. ^rust-data-types https://doc.rust-lang.org/book/ch03-02-data-types.html
  2. ^typescript https://www.typescriptlang.org/
  3. ^parse-error https://doc.rust-lang.org/book/ch02-00-guessing-game-tutorial.html#comparing-the-guess-to-the-secret-number
  4. ^rust-scalar-types https://doc.rust-lang.org/book/ch03-02-data-types.html#scalar-types
  5. ^rust-integer-types https://doc.rust-lang.org/book/ch03-02-data-types.html#integer-types
  6. ^rust-integer-overflow https://doc.rust-lang.org/book/ch03-02-data-types.html#integer-overflow
  7. ^rust-floast-types https://doc.rust-lang.org/book/ch03-02-data-types.html#floating-point-types
  8. ^rust-bool-type https://doc.rust-lang.org/book/ch03-02-data-types.html#the-boolean-type
  9. ^rust-string https://doc.rust-lang.org/book/ch08-02-strings.html#storing-utf-8-encoded-text-with-strings
  10. ^rust-compound-types https://doc.rust-lang.org/book/ch03-02-data-types.html#compound-types
  11. ^tuple https://doc.rust-lang.org/book/ch03-02-data-types.html#the-tuple-type
  12. ^rust-array-type https://doc.rust-lang.org/book/ch03-02-data-types.html#the-array-type
  13. ^rust-array-invalid-index https://doc.rust-lang.org/book/ch03-02-data-types.html#invalid-array-element-access
  14. ^经典老梗 https://zhuanlan.zhihu.com/p/355468963
  15. ^rust-vector https://doc.rust-lang.org/book/ch08-01-vectors.html

编辑于 2022-11-30 16:12・IP 属地广东