Rust 从入门到摔门而出门 (二) 数据类型
Rust的数据类型有两种:标量数据类型和复合数据类型,
- 标量数据类型只有一个值,有 整型、浮点型、布尔、字符 四种类型。
- 复合数据类型多个值组合成一个类型,有 元组和数组。
标量类型
整型
整数是一个没有小数的数组,在Rust中整数分为有无符号(-),代表数字能否负值,有符号数以补码形式存储。
Rust中数字类型默认使用 i32。
| 长度 | 有符号 | 无符号 |
|---|---|---|
| 8-bit | i8 | u8 |
| 16-bit | i16 | u16 |
| 32-bit | i32 | u32 |
| 64-bit | i64 | u64 |
| 128-bit | i128 | u128 |
| arch | isize | usize |
isize 和 usize 类型依赖运行程序的计算机架构:64 位架构上它们是 64 位的,32 位架构上它们是 32 位的。
取值范围:
- i8的取值范围为 -128 到 127
- u8的取值范围为 0 到 255
- i16的取值范围为 -32768 到 32767
- u16的取值范围为 0 到 65535
- i32的取值范围为 -2147483648 到 2147483647
- u32的取值范围为 0 到 4294967295
- i64的取值范围为 -9223372036854775808 到 9223372036854775807
- u64的取值范围为 0 到 18446744073709551615
- i128的取值范围为 -170141183460469231731687303715884105728 到 170141183460469231731687303715884105727
- u128的取值范围为 0 到 340282366920938463463374607431768211455
isize 和 usize 的取值范围依赖于他在运行的计算机架构。
整型中使用不同进制:
| 数字字面值 | 例子 |
|---|---|
| 十进制 | 98_123 |
| 十六进制 | 0xff |
| 八进制 | 0o77 |
| 二进制 | 0b1111_0000 |
| 单字节字符(仅限于u8) | b'a' |
整型溢出
let a: u8 = 256;
在rust中定义一个变量a:u8,u8的取值范围是 0 到255,如果赋值256 超出取值范围,被称为整型溢出这会导致两种情况:
- debug编译模式时 Rust 检查这类问题并使程序 panic,因为错误而退出。
- 使用 --release 构建时 使用 --release flag 在 release 模式中构建时,Rust 不会检测会导致 panic 的整型溢出。相反发生整型溢出时,Rust 会进行一种被称为二进制补码的操作。简而言之,比此类型能容纳最大值还大的值会回绕到最小值,值 256 变成 0,值 257 变成 1,依此类推。程序不会 panic,不过变量可能也不会是你所期望的值。依赖整型溢出 wrapping 的行为被认为是一种错误。
浮点型
在Rust中的浮点型,有两种 f32 和 f64,分别占 32位和64位。Rust中默认类型是 f64,在目前的计算机中 f64 和 f32 速度几乎一样,不过精度更高,所有的浮点型都是有符号的。
fn main(){
let x = 1.2; // f64
let y: f64 = 2.4; // f32
}
浮点数采用 IEEE-754 标准表示。f32 是单精度浮点数,f64 是双精度浮点数。
数值运算
Rust中支持 加法、减法、乘法、除法和取余。整数除法会向零舍入到最接近的整数。
fn main() {
// addition
let sum = 5 + 10;
println!("数字结果 sum {sum}");
//数字结果 sum 15
// subtraction
let difference = 95.5 - 4.3;
println!("数字结果 difference {difference}");
//数字结果 difference 91.2
// multiplication
let product = 4 * 30;
println!("数字结果 product {product}");
// 数字结果 product 120
// division
let quotient = 56.7 / 32.2;
println!("数字结果 quotient {quotient}");
// 数字结果 quotient 1.7608695652173911
let truncated = -5 / 3;
println!("数字结果 truncated {truncated}");
// 数字结果 truncated -1
let truncated2 = -5.0 / 3.0;
println!("数字结果 truncated {truncated2}");
// 数字结果 truncated -1.6666666666666667
// remainder
let remainder = 43 % 5;
println!("数字结果 remainder {remainder}");
//数字结果 remainder 3
}
在上段代码中 -5/3 结果是 -1, 在Rust中整数除法会 向零舍入,取整。 如果代码想要避免这种情况可以转成浮点数 -5.0 / 3.0 结果是 -1.6666666666666667。
布尔值
Rust中的布尔值和其他大部分语言一样,有两个值 true 和 false,使用 bool标识。
let t = true;
let f: bool = false;
字符类型
Rust 的 char 类型是语言中最原生的字母类型。
fn main() {
let str = 'string';
let str2: char = 'string'; // with explicit type annotation
let heart_eyed_cat = '😝';
}
复合类型
复合类型可以将多个值组合成一个类型。Rust 有两个原生的复合类型:元组(tuple)和数组(array)。
元组
元组是一个将多个其他类型的值组合进一个复合类型的主要方式,元组的长度固定:一旦声明,其长度不会增大或缩小。
let tup: (i32, f64, char) = (123, 3.14, '哈哈');
上段代码中声明了 元组 tup,指有三个可以设置不同的数据类型。
let tup: (i32, f64, char) = (123, 3.14, '哈哈');
let (a, b, c) = tup;
println!("a: {a}, b: {b}, c: {c}");
上段代码中将元组进行了解构。
let tup: (i32, f64, char) = (123, 3.14, '哈哈');
let a = tup.0;
let b = tup.1;
let c = tup.2;
上段代码通过索引的方式(.),进行访问获取值。
不带任何值的元组,在Rust中叫做单元元组。这种值以及对应的类型都写作 (),表示空值或空的返回类型。如果表达式不返回任何其他值,则会隐式返回单元值。
数组类型
数组也包含多个值,和元组不同的是,数组的每个元素的数据类型必须相同。Rust中数组的长度是固定的,这是与一些其他语言中的数组不同。
let arr = [ 1, 2, 3, 4, 5 ];
let arr2: [i32; 5] = [ 1, 2, 3, 4, 5 ];
let arr3 = [11; 5];
上段代码:
- 变量 arr2的
[i32; 5]这里i32表示每个值的数据类型,分号后的5表示该数组包含5个元素 - 变量 arr3的
[11; 5]表示生成数组长度5,初始值为 11。等同于let arr3 = [ 11, 11, 11, 11, 11 ];相同的效果,[11; 5]的写法更加简洁。
访问素组元素
let arr = [ 1, 2, 3, 4, 5 ];
let a = arr[0];
let b = arr[1];
数组是可以在栈上分配的已知固定大小的单个内存块。可以使用索引来访问数组的元素,Rust和大部分语言一样从0开始。