Rust编程:入门、实战与进阶
上QQ阅读APP看书,第一时间看更新

2.2 基本数据类型

数据类型是Rust作为强类型的静态编译语言的基础。有了数据类型,Rust才能对不同的类型抽象出不同的运算,开发者才能在更高的层次上操作数据,而不用关心具体的存储和运算细节。Rust的基本数据类型有整数类型、浮点数类型、布尔类型、字符类型、范围类型等。

2.2.1 整数类型

整数是指没有小数部分的数字,比如0、1、-2、99999等,而0.0、1.0、-2.1、9.99999都不是整数。根据有无符号,整数可以分为有符号整型和无符号整型。有符号和无符号整型代表能否存储负的整数值。有符号整型可以存储正数,也可以存储负数,而无符号整型只能存储正数。按照存储大小,整数类型可以进一步分为1字节、2字节、4字节、8字节、16字节(1字节=8位)。表2-1列出了整数类型所有的细分类型,Rust默认的整数类型是i32。isize和usize主要作为数组或集合的索引类型使用,其长度依赖于运行程序的计算机系统。在64位计算机系统上,其长度是64位;在32位计算机系统上,其长度是32位。

表2-1 Rust的整数类型

021-01

下面介绍整数类型声明的语法,第1行代码是标准的整数类型变量声明;第2行代码创建的数字字面量后使用类型后缀,表示这是一个u32类型;第3行代码没有指定类型,也没有加类型后缀,Rust默认整数类型为i32;第4~6行代码分别使用前缀0b、0o和0x表示二进制、八进制和十六进制的数字。

1  let integer1: u32 = 17;       // 类型声明
2  let integer2 = 17u32;         // 类型后缀声明
3  let integer3 = 17;            // 默认i32类型
4  let integer4: u32 = 0b10001;  // 二进制
5  let integer5: u32 = 0o21;     // 八进制
6  let integer6: u32 = 0x11;     // 十六进制
7  let integer7 = 50_000;        // 数字可读性分隔符_

为了方便阅读数值较大的数字,Rust允许使用下划线“_”作为虚拟分隔符来对数字进行可读性分隔。比如,为了提高50000的可读性,可以写成50_000。Rust在编译时会自动移除数字可读性分隔符“_”。

有符号整数类型的数值范围是-2n-1~2n-1-1,无符号整数类型的数值范围是0~2n-1,这里n是长度。比如,i8的数值范围是-27~27-1,也就是-128~127。u8的数值范围是0~28-1,也就是0~255。

如果某个变量的值超出了给定的数值范围,将会发生整型溢出。编译器将其视为一种错误。比如,如果一个u8类型的变量被赋值256,就会发生整型溢出而导致程序错误。

2.2.2 浮点数类型

浮点数是指带小数点的数字,比如0.0、1.0、-2.1、9.99999等。按照存储大小,浮点数分为f32和f64两类。Rust默认的浮点数类型是f64。

  • f32:单精度浮点数,小数点后至少有6位有效数字。
  • f64:双精度浮点数,小数点后至少有15位有效数字。

浮点数类型声明的语法如下,第1行代码是标准的浮点数类型变量声明。第2行代码创建的浮点数字面量后使用类型后缀,表示这是一个f32类型。第3行代码没有指定类型,也没有加类型后缀。第4行代码浮点数支持使用数字可读性分隔符“_”。

1  let float1: f32 = 1.1;        // 类型声明
2  let float2 = 2.2f32;          // 类型后缀声明
3  let float3 = 3.3;             // 默认f64类型
4  let float4 = 11_000.555_001;  // 数字可读性分隔符_

2.2.3 布尔类型

Rust使用bool来声明布尔类型的变量,声明的语法如下所示。布尔类型只有两个可能的取值,即true或false,一般用于逻辑表达式中。

1  let t: bool = true;           // 显式类型声明
2  let f = false;                // 隐式类型声明

2.2.4 字符类型

Rust使用UTF-8作为底层的编码。字符类型代表的是一个Unicode标量值(Unicode Scalar Value),包括数字、字母、Unicode和其他特殊字符。每个字符占4个字节。字符类型char由单引号来定义,其声明语法如下所示。

022-01

2.2.5 范围类型

范围类型常用来生成从一个整数开始到另一个整数结束的整数序列,有左闭右开和全闭两种形式,比如(1..5)是左闭右开区间,表示生成1、2、3、4这4个数字;(1..=5)是全闭区间,表示生成1、2、3、4、5这5个数字。范围类型自带一些方法,如代码清单2-4所示。第9行代码中的rev方法可以将范围内的数字顺序反转,第14行代码中的sum方法可以对范围内的数字进行求和。

代码清单2-4 范围类型

 1  fn main() {
 2      print!("(1..5): ");
 3      for i in 1..5 {
 4          print!("{} ", i);
 5      }
 6      println!();
 7    
 8      print!("(1..=5).rev: ");
 9      for i in (1..=5).rev() {
10          print!("{} ", i);
11      }
12      println!();
13    
14      let sum: i32 = (1..=5).sum();
15      println!("1 + 2 + 3 + 4 + 5 = {}", sum);
16  }
17
18  // (1..5): 1 2 3 4
19  // (1..=5).rev: 5 4 3 2 1
20  // 1 + 2 + 3 + 4 + 5 = 15