博主未授权任何人或组织机构转载博主任何原创文章,感谢各位对原创的支持!
博主链接
文章目录
Rust 基础数据类型介绍(一)
Rust中的数据类型如下所示,我会分多篇博客来介绍,下面先看一个总览:
一、固定宽度的数值类型
Rust中数值类型的名称都遵循一种统一的模式,也就是位数
表面它的宽度,以前缀
表明它的用法,如下图所示:
1.1 整型
1.1.1 无符号整型
Rust 的无符号整型会使用它们的完整范围来表示正值和 0,如下表所示:
1.1.2 有符号整型
Rust 的有符号整型会使用二进制补码表示,使用与相应的无符号类型相同的位模式来覆盖正值和负值的范围,如下表所示:
Rust会将u8
类型作为字节值。例如,从二进制文件或套接字中读取数据时会产生一个 u8 值构成的流。usize
类型和isize
类型类似于C和C++中的size_t
和ptrdiff_t
,他们的精度与目标机器上地址空间的大小一致,即在32位架构上是32位长,在64位架构上是64位长。Rust要求数组索引是usize值,用来表示数组或向量大小或数据结构中元素数量的值通常也是usize类型
。
1.1.3 整型字面量
Rust中的整型字面量
可以带上一个后缀来指示它的类型,例如,65u8是 u8类型。如果整型字面量没有携带类型后缀,Rust会延迟确定
其类型,如果有多个候选类型,且包含i32,则选择 i32,否则报告类型歧义错误。
前缀 0x
、0o
和 0b
分别表示十六进制字面量、八进制字面量和二进制字面量。为了易读性,可以在数字之间任意插入下划线
,例如,4_294_967_295。下划线的具体位置无关紧要
,因此也可以将十六进制数或二进制数按 4 位数字而非 3 位数字进行分组(如 0xffff_ffff),或分隔开数字的类型后缀(如 127_u8)。
1.1.4 字节字面量
Rust为 u8 类型提供了字节字面量
,例如,b’x’ 表示以字符 x 的ASCII码作为 u8的值。需要注意的是只有ASCII字符才能出现在字节字面量中
。下面几个字符是需要使用转义字符来表示的:
1.2 浮点类型
Rust 提供了 IEEE 单精度浮点类型和 IEEE 双精度浮点类型。这些类型包括正无穷大和负无穷大、不同的正零值和负零值,以及非数值。如下表所示:
Rust 的 f32 和 f64 分别对应于 C 和 C++(在支持 IEEE 浮点的实现中)以及 Java(始终使用 IEEE 浮点)中的 float 类型和 double 类型。
如果浮点字面量缺少类型后缀,那么Rust会检查上下文以查看值的使用方式,如果发现两种浮点类型都合适,就会默认选择f64
。
1.3 转换运算符
可以使用as
运算符将一种整型类型转换为另一种整型类型。例如,
assert_eq!( 10_i8 as u16, 10_u16); // 范围内转换
assert_eq!( 2525_u16 as i16, 2525_i16); // 范围内转换
assert_eq!( -1_i16 as i32, -1_i32); // 带符号扩展
assert_eq!(65535_u16 as i32, 65535_i32); // 填零扩展
// 超出目标范围的转换生成的值等于原始值对2N取模的值,
// 其中N是按位算的目标宽度。有时这也称为“截断”
assert_eq!( 1000_i16 as u8, 232_u8);
assert_eq!(65535_u32 as i16, -1_i16);
assert_eq!( -1_i8 as u8, 255_u8);
assert_eq!( 255_u8 as i8, -1_i8);
1.4 检查算法、回绕算法、饱和算法和溢出算法
当整型算术运算溢出时,Rust在调试
构建中会出现 panic。而在发布
构建中,运算会回绕,即它生成的值等于“数学意义上正确的结果”对“值类型范围”取模的值(在任何情况下不会出现像C和C++中那样出现“溢出未定义”的行为)。
如果这种默认行为不是你想要的,则整型提供的某些方法可以让你准确地阐明自己期望的行为。
1.4.1 检查运算
检查运算会返回结果的Option 值
:如果数学意义上正确的结果可以表示为该类型的值,那么就为 Some(v),否则为 None。
// 10与20之和可以表示为u8
assert_eq!(10_u8.checked_add(20), Some(30));
// 很遗憾,100与200之和不能表示为u8
assert_eq!(100_u8.checked_add(200), None);
// 做加法。如果溢出,则会出现panic
let sum = x.checked_add(y).unwrap();
// 奇怪的是,在某种特殊情况下,带符号的除法也会溢出。
// 带符号的n位类型可以表示-2^(n-1),但不足以表示2^(n-1)
assert_eq!((-128_i8).checked_div(-1), None);
1.4.2 回绕运算
回绕运算会返回与“数学意义上正确的结果”对“值类型范围”取模的值相等的值。
// 第一个结果可以表示为u16,第二个则不能,所以会得到250000 对216的模
assert_eq!(100_u16.wrapping_mul(200), 20000);
assert_eq!(500_u16.wrapping_mul(500), 53392);
// 对有符号类型的运算可能会回绕为负值
assert_eq!(500_i16.wrapping_mul(500), -12144);
// 在移位运算中,移位距离会在值的大小范围内回绕,
// 所以在16位类型中移动17位就相当于移动了1位
assert_eq!(5_i16.wrapping_shl(17), 10);
1.4.3 饱和运算
饱和运算会返回最接近“数学意义上正确结果”的可表达值。换句话说,结果“紧贴着”该类型可表达的最大值和最小值。
assert_eq!(32760_i16.saturating_add(10), 32767);
assert_eq!((-32760_i16).saturating_sub(10), -32768);
1.4.4 溢出运算
溢出运算会返回一个元组 (result, overflowed)
,其中 result 是函数的回绕版本所返回的内容,而 overflowed 是一个布尔值,指示是否发生过溢出。
assert_eq!(255_u8.overflowing_sub(2), (253, false));
assert_eq!(255_u8.overflowing_add(2), (1, true));
前缀 checked_、wrapping_、saturating_ 或 overflowing_ 后面可以跟着的运算名称如下表所示: