Rust基本数据类型
Rust 每个值都有其确切的数据类型,总的来说可以分为两类:基本类型和复合类型。 基本类型意味着它们往往是一个最小化原子类型,无法解构为其它类型(一般意义上来说),由以下组成:
- 数值类型: 有符号整数 (
i8
,i16
,i32
,i64
,isize
)、 无符号整数 (u8
,u16
,u32
,u64
,usize
) 、浮点数 (f32
,f64
)、以及有理数、复数 - 字符串:字符串字面量和字符串切片
&str
- 布尔类型:
true
和false
- 字符类型: 表示单个 Unicode 字符,存储为 4 个字节
- 单元类型: 即
()
,其唯一的值也是()
1.数值类型
长度 | 有符号类型 | 无符号类型 |
---|---|---|
8 位 | i8 |
u8 |
16 位 | i16 |
u16 |
32 位 | i32 |
u32 |
64 位 | i64 |
u64 |
128 位 | i128 |
u128 |
视架构而定 | isize |
usize |
整形字面量可以用下表的形式书写:
数字字面量 | 示例 |
---|---|
十进制 | 98_222 |
十六进制 | 0xff |
八进制 | 0o77 |
二进制 | 0b1111_0000 |
字节 (仅限于 u8 ) |
b'A' |
2.浮点类型
浮点类型数字 是带有小数点的数字,在 Rust 中浮点类型数字也有两种基本类型: f32
和 f64
,分别为 32 位和 64 位大小。默认浮点类型是 f64
,在现代的 CPU 中它的速度与 f32
几乎相同,但精度更高。
下面是一个演示浮点数的示例:
1 | fn main() { |
3.序列(Range)
Rust 提供了一个非常简洁的方式,用来生成连续的数值,例如 1..5
,生成从 1 到 4 的连续数字,不包含 5 ;1..=5
,生成从 1 到 5 的连续数字,包含 5,它的用途很简单,常常用于循环中:
1 | for i in 1..=5 { |
最终程序输出:
1 | 1 |
序列只允许用于数字或字符类型,原因是:它们可以连续,同时编译器在编译期可以检查该序列是否为空,字符和数字值是 Rust 中仅有的可以用于判断是否为空的类型。如下是一个使用字符类型序列的例子:
1 | for i in 'a'..='z' { |
4.有理数和复数
Rust 的标准库相比其它语言,准入门槛较高,因此有理数和复数并未包含在标准库中:
- 有理数和复数
- 任意大小的整数和任意精度的浮点数
- 固定精度的十进制小数,常用于货币相关的场景
好在社区已经开发出高质量的 Rust 数值库:num。
按照以下步骤来引入 num
库:
- 创建新工程
cargo new complex-num && cd complex-num
- 在
Cargo.toml
中的[dependencies]
下添加一行num = "0.4.0"
- 将
src/main.rs
文件中的main
函数替换为下面的代码 - 运行
cargo run
1 | use num::complex::Complex; |
总结
之前提到了过 Rust 的数值类型和运算跟其他语言较为相似,但是实际上,除了语法上的不同之外,还是存在一些差异点:
- Rust 拥有相当多的数值类型. 因此你需要熟悉这些类型所占用的字节数,这样就知道该类型允许的大小范围以及你选择的类型是否能表达负数
- 类型转换必须是显式的. Rust 永远也不会偷偷把你的 16bit 整数转换成 32bit 整数
- Rust 的数值上可以使用方法. 例如你可以用以下方法来将
13.14
取整:13.14_f32.round()
,在这里我们使用了类型后缀,因为编译器需要知道13.14
的具体类型
5.函数要点
- 函数名和变量名使用蛇形命名法(snake case),例如
fn add_two() -> {}
- 函数的位置可以随便放,Rust 不关心我们在哪里定义了函数,只要有定义即可
- 每个函数参数都需要标注类型
1 | fn add(i: i32, j: i32) -> i32 { |
返回值:
无返回值()
- 函数没有返回值,那么返回一个
()
- 通过
;
结尾的表达式返回一个()
当用 !
作函数返回类型的时候,表示该函数永不返回( diverge function ),特别的,这种语法往往用做会导致程序崩溃的函数:
6.练习
数值类型 - Rust By Practice( Rust 练习实践 )
1 | fn main() { |
1 |
|
1 | fn main() { |
1 |
|
1 | fn main() { |
1 | #使用两种方法来让下面代码工作 |
序列Range
- 🌟🌟 两个目标: 1. 修改
assert!
让它工作 2. 让println!
输出: 97 - 122
1 | fn main() { |
1 | use std::ops::{Range, RangeInclusive}; |
1 | use std::mem::size_of_val; |
语句与表达式
1 | fn main() { |
函数
7.总结:
1.let x = 2.0; // f64
2.比较浮点数(0.1_f64 + 0.2 - 0.3).abs() < 0.00001
3.编译器会进行自动推导,给予twenty i32的类型 let twenty = 20;
4.按照补码循环溢出规则处理et b = 255_u8.wrapping_add(20); // 19
在 u8 的情况下,256 变成 0,257 变成 1,
5.(1..5) 表示从 1 到 5(不包括 5)半开区间的范围
6.(1..=5) 表示从 1 到 5(包括 5)半闭区间的范围
6.表达式不能包含分号。表达式总要返回值
7.返回值为!的表达式
1 | loop {} |
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 yengii@qq.com