Rust 是 静态类型(statically typed)语言,也就是说在编译时就必须知道所有变量的类型。
在 Rust 中,每一个值都属于某一个 数据类型(data type),这告诉 Rust 它被指定为何种数据,以便明确数据处理方式。我们将看到两类数据类型子集:标量(scalar)和复合(compound)。
标量类型
标量(scalar)类型代表一个单独的值。Rust 有四种基本的标量类型:整型、浮点型、布尔类型和字符类型。
复合类型
复合类型(Compound types)可以将多个值组合成一个类型。Rust 有两个原生的复合类型:元组(tuple)和数组(array)。
整型,浮点型
整型默认是i32类型,浮点型默认是f64类型。
两个不同的类型的数据不能运算,包括求余,加,减,乘,除。
Rust 中的整型
长度 有符号 无符号
8-bit i8 u8
16-bit i16 u16
32-bit i32 u32
64-bit i64 u64
128-bit i128 u128
arch isize usize
每一个有符号的变体可以储存包含从 -(2n - 1) 到 2n - 1 - 1 在内的数字,这里 n 是变体使用的位数。所以 i8 可以储存从 -(27) 到 27 - 1 在内的数字,也就是从 -128 到 127。无符号的变体可以储存从 0 到 2n - 1 的数字,所以 u8 可以储存从 0 到 28 - 1 的数字,也就是从 0 到 255。
另外,isize 和 usize 类型依赖运行程序的计算机架构:64 位架构上它们是 64 位的, 32 位架构上它们是 32 位的。
整型溢出
比方说有一个
u8
,它可以存放从零到255
的值。那么当你将其修改为256
时会发生什么呢?这被称为 “整型溢出”(“integer overflow” ),这会导致以下两种行为之一的发生。当在 debug 模式编译时,Rust 检查这类问题并使程序 panic,这个术语被 Rust 用来表明程序因错误而退出。第九章 “panic!
与不可恢复的错误” 部分会详细介绍 panic。
在 release 构建中,Rust 不检测溢出,相反会进行一种被称为二进制补码包装(two’s complement wrapping)的操作。简而言之,值256
变成0
,值257
变成1
,依此类推。依赖整型溢出被认为是一种错误,即便可能出现这种行为。如果你确实需要这种行为,标准库中有一个类型显式提供此功能,Wrapping
。 为了显式地处理溢出的可能性,你可以使用标准库在原生数值类型上提供的以下方法:
- 所有模式下都可以使用
wrapping_*
方法进行包装,如wrapping_add
- 如果
check_*
方法出现溢出,则返回None
值- 用
overflowing_*
方法返回值和一个布尔值,表示是否出现溢出- 用
saturating_*
方法在值的最小值或最大值处进行饱和处理
浮点型:f32 f64
在现代 CPU 中,它与 f32 速度几乎一样,不过精度更高。所有的浮点型都是有符号的。
浮点数采用 IEEE-754 标准表示。f32 是单精度浮点数,f64 是双精度浮点数。
数据运算
let a:i8 = 9;
let b:i64 = 2;
let x = a*b;
println!("The value of x is: {}", x);
error[E0308]: mismatched types #不匹配的类型
类型不同,所以报错。
let a:i64 = 90000;
let b:i64 = 2;
let x = a*b;
println!("The value of x is: {}", x);
The value of x is: 180000
数据运算的结果x的类型自动变成了运算数据一样的类型。
let a = 9;
let b:i64 = 2;
let x = a*b;
println!("The value of x is: {}", x);
The value of x is: 18
a是整型,理论上默认应该是i32类型,但是数据运算表达式的存在,编译时做了自动类型检查,会被设置成和变量b一样的i64整型
println!("The value of x is: {}", 1u32 - 2);
error: this arithmetic operation will overflow
1 - 2 = -1;但是结果应该是一个无符号的,所以-1这个数据溢出了。
布尔型
Rust 中的布尔类型有两个可能的值:true 和 false。Rust 中的布尔类型使用 bool 表示。
fn main() {
let t = true;
let f: bool = false; // 显式指定类型注解
}
字符类型
Rust的 char 类型是语言中最原生的字母类型。
我们用单引号声明 char 字面量,而与之相反的是,使用双引号声明字符串字面量。Rust 的 char 类型的大小为四个字节(four bytes),并代表了一个 Unicode 标量值(Unicode Scalar Value),这意味着它可以比 ASCII 表示更多内容。在 Rust 中,拼音字母(Accented letters),中文、日文、韩文等字符,emoji(绘文字)以及零长度的空白字符都是有效的 char 值。
由于中文文字编码有两种(GBK 和 UTF-8),所以编程中使用中文字符串有可能导致乱码的出现,这是因为源程序与命令行的文字编码不一致,所以在 Rust 中字符串和字符都必须使用 UTF-8 编码,否则编译器会报错。
let s = 's';
let str = "abc"
元组
元组是一个可以包含各种类型值的组合。元组使用括号 () 来构造(construct),而每个元组自身又是一个类型标记为 (T1, T2, ...) 的值,其中 T1、T2 是每个元素的类型。
元组长度固定:一旦声明,其长度不会增大或缩小。
获取元组的值,有两种方式:1.使用 tup.下标 2. 解构
let x = (500, 6.4, 1);
let a = x.0;
let (x, y, z) = x;
let b = x.2
let x: (i32, f64, u8) = (300, 7.4, 8);
let a = x.0;
数组
数组中的每个元素的类型必须相同。Rust 中的数组与一些其他语言中的数组不同,Rust中的数组长度是固定的。
当你想要在栈(stack)而不是在堆(heap)上为数据分配空间,或者是想要确保总是有固定数量的元素时(比如12个月份),数组非常有用。
但是数组并不如 vector 类型灵活。vector 类型是标准库提供的一个 允许 增长和缩小长度的类似数组的集合类型。
数组是可以在堆栈上分配的已知固定大小的单个内存块。可以使用索引来访问数组的元素。
let months = ["January", "February", "March", "April", "May", "June", "July",
"August", "September", "October", "November", "December"];
let m = months[2]
也可以像这样编写数组的类型:在方括号中包含每个元素的类型,后跟分号,再后跟数组元素的数量。
let a: [i32; 5] = [1, 2, 3, 4, 5];
let a = [3; 5]; // 等价于 let a = [3,3,3,3,3]
let m = a[1]
网友评论