找回密码
 立即注册
首页 业界区 安全 Rust从入门到精通04-数据类型

Rust从入门到精通04-数据类型

煅汾付 昨天 21:25
Rust 是 静态类型statically typed)语言,也就是说在编译时就必须知道所有变量的类型。
在 Rust 中,每一个值都属于某一个 数据类型(data type),分为两大类:
①、标量(基本数据类型)(scalar):整型、浮点型、布尔类型、字符类型
②、复合(compound):元祖(tuple)、数组(array)、结构体(struct)
0、静态类型和动态类型区别

静态类型和动态类型是编程语言的两种基本类型系统。如果一门语言不谈数据类型,大概率是动态类型。
本质上它们主要的区别在于类型检查发生的时间和方式。
静态类型语言

  • 在编译时期进行类型检查。这意味着在你的代码运行之前,编译器就会检查数据类型的正确性。如果数据类型不匹配,编译器将引发错误,代码无法编译。
  • 由于静态类型语言在编译时期就完成了类型检查,因此它们通常具有更好的性能,因为运行时没有类型检查的开销。
  • 静态类型语言通常需要显式声明变量的类型。这使得代码更具可读性,并且更易于维护和调试,因为类型信息可以帮助开发者理解变量和函数的行为。
  • 静态类型语言的例子包括:Java、C++、C#、Rust 等。
动态类型语言

  • 在运行时期进行类型检查。这意味着在代码执行时,解释器会检查数据类型的正确性。如果数据类型不匹配,将引发运行时错误。
  • 动态类型语言在编写代码时具有更大的灵活性,因为你不需要显式声明变量的类型。这使得代码更简洁,但也可能导致类型错误更难检测和调试。
  • 动态类型语言的性能通常不如静态类型语言,因为它们在运行时需要进行类型检查。
  • 动态类型语言的例子包括:Python、Ruby、JavaScript、PHP 等。
1、标量-基本数据类型 scalar

每个类型有一个单独的值。
1.1 整型

表示没有小数部分的数字,分为有符号(以 i 开头)和无符号(以 u 开头)整型。
数字类型的默认类型是 i32。
长度有符号无符号8-biti8u816-biti16u1632-biti32u3264-biti64u64128-biti128u128archisizeusize每一个有符号的整型可以储存包含从 -($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 位的。
这里我说下为啥会有这种依赖计算机架构的数据长度,主要有两点:
①、性能优化:与系统架构直接对应,这意味着它们可以被优化以适应特定平台的最佳性能。例如,在 64 位系统上,usize 可以高效地处理较大的数据结构,因为它能够表示的地址空间更大。
②、跨平台兼容:使用 usize 和 isize 可以让同一段 Rust 代码在不同架构的系统上运行而无需修改。这对于编写库或框架特别重要,因为这些库或框架需要在各种硬件和操作系统上工作。
1.1.1 所有数字字面量,可以在任意地方添加下划线_

①、十进制字面量 12_222,使用下划线按三位数字一组隔开
②、十六进制字面量 0xff,使用0x开头
③、八进制字面量 0o66,使用0o(小写字母o)开头
④、二进制字面量 0b1111_0000,使用0b开头,按4位数字一组隔开
⑤、字符的字节表示 b'A',对一个ASCII字符,在其前面加b前缀,直接得到此字符的ASCII码值
  1. fn int_test(){
  2.     //所有数字字面量,可以在任意地方添加下划线_
  3.     let x : u32 = 1_2_3;
  4.     let y = x + 1;
  5.     //打印结果为 124
  6.     println!("{}",y);
  7. }
复制代码
  1. fn main() {
  2.     let i1 = 12_222;
  3.     let i2 = 0xff;
  4.     let i3 = 0o66;
  5.     let i4 = 0b1111_0000;
  6.     let i5 =  b'A';
  7.     // i1=12222;i2=255;i3=54;i4=240;i5=65
  8.     println!("i1={};i2={};i3={};i4={};i5={}",i1,i2,i3,i4,i5)
  9. }
复制代码
1.1.2 字面量可以跟类型后缀,表示数字具体类型
  1. //字面量可以跟类型后缀,表示数字具体类型
  2. fn int_test2(){
  3.     let x = 123i32;
  4.     let y = x + 1;
  5.     //打印结果为 124
  6.     println!("{}",y);
  7. }
复制代码
1.1.3 直接对整型字面量调用函数
  1. //直接对整型字面量调用函数
  2. fn int_test3(){
  3.     let x : i32 = 9;
  4.     //打印结果为 729
  5.     println!("9 power 3 = {}",x.pow(3));
  6. }
复制代码
1.1.4 整数溢出

Rust 对于整数溢出的处理方式如下:
①、默认情况下,在debug模式下编译器会自动插入整数溢出检查,一旦发生溢出,则会引发 panic;
②、在 release 模式下(使用 --release 参数),不检查整数溢出,而是自动舍弃高位的方式。
要显式处理可能的溢出,可以使用标准库针对原始数字类型提供的这些方法:

  • 使用 wrapping_* 方法在所有模式下都按照补码循环溢出规则处理,例如 wrapping_add
  • 如果使用 checked_* 方法时发生溢出,则返回 None 值
  • 使用 overflowing_* 方法返回该值和一个指示是否存在溢出的布尔值
  • 使用 saturating_* 方法使值达到最小值或最大值
  1. fn main() {
  2.     let a : u8 = 255;
  3.     let b = a.wrapping_add(20);
  4.     println!("{}", b);  // 19
  5. }
复制代码
这里其实也体现了 rust 这门语言的安全性,大家如果有项目开发经验,对于整数溢出导致的bug,其实是很难排查的,项目没有任何错误日志,但是得到的数据就是不对,往往令人崩溃,而 rust 直接程序 panic,这样极大的方便我们去排查问题。
1.1.5 如何选择

通常默认类型 i32 即可,它通常是最快的,性能最好的。
isize 和 usize 的主要应用场景是用作集合的索引。
1.2 浮点

Rust 有两个原生的 浮点数floating-point numbers)类型,它们是带小数点的数字。是基于 IEEE 754-2008 标准的浮点类型,分别是 f32 和 f64,分别占 32 位和 64 位。默认类型是 f64,因为在现代 CPU 中,它与 f32 速度几乎一样,不过精度更高。
  1. fn float_test(){
  2.     //123.0 f32类型
  3.     let f1 = 123.0f32;
  4.     //0.1 f64类型
  5.     let f2 = 0.1f64;
  6. }
复制代码
1.2.1 浮点数陷阱

浮点数基本上是近似数表达,因为浮点数是基于二进制实现的。
比如对于 0.1 ,在十进制是精确存在的,但是在二进制上并不存在精确的表达形式,所以要避免对浮点数进行相等性测试。
  1. fn main() {
  2.     assert!(0.1 + 0.2 == 0.3);
  3. }
复制代码
运行报错。因为二进制精度问题,导致了 0.1 + 0.2 并不严格等于 0.3,它们可能在小数点 N 位后存在误差。
如果非要比较,考虑用这种方式 (0.1_f64 + 0.2 - 0.3).abs() < 0.00001 ,具体小于多少,取决于你对精度的需求。
1.png

1.3 布尔类型

布尔类型(bool)代表的是“是”和“否”的二值逻辑。它有两个值:
true和false
一般用在逻辑表达式中,可以执行“与”“或”“非”等运算,常用于条件判断和控制流操作。
布尔值占用内存的大小为 1 个字节
  1. fn bool_test(){
  2.     let x = true;
  3.     //取反运算
  4.     let y = !x;
  5.     //逻辑与,带短路功能
  6.     let z = x && y;
  7.     //逻辑或,带短路功能
  8.     let z = x || y;
  9.          
  10.           if x {
  11.         println!("Rust is awesome!");
  12.     }
  13. }
复制代码
1.4、字符类型

字符类型由 char 表示。它可以描述任何一个符合 unicode 标准的字符值。在代码中,单个的字符字面量用单引号包围(不同于字符串用双引号):
1.4.1 4个字节字符

[code]let heart_eyed_cat = '
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
您需要登录后才可以回帖 登录 | 立即注册