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的整数类型
下面介绍整数类型声明的语法,第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由单引号来定义,其声明语法如下所示。
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