博主未授权任何人或组织机构转载博主任何原创文章,感谢各位对原创的支持!
博主链接



Rust 基础数据类型介绍(一)

       Rust中的数据类型如下所示,我会分多篇博客来介绍,下面先看一个总览:

一、固定宽度的数值类型

       Rust中数值类型的名称都遵循一种统一的模式,也就是位数表面它的宽度,以前缀表明它的用法,如下图所示:

1.1 整型

1.1.1 无符号整型

       Rust 的无符号整型会使用它们的完整范围来表示正值和 0,如下表所示:

1.1.2 有符号整型

       Rust 的有符号整型会使用二进制补码表示,使用与相应的无符号类型相同的位模式来覆盖正值和负值的范围,如下表所示:

Rust会将u8类型作为字节值。例如,从二进制文件或套接字中读取数据时会产生一个 u8 值构成的流。usize类型和isize类型类似于C和C++中的size_tptrdiff_t,他们的精度与目标机器上地址空间的大小一致,即在32位架构上是32位长,在64位架构上是64位长。Rust要求数组索引是usize值,用来表示数组或向量大小或数据结构中元素数量的值通常也是usize类型

1.1.3 整型字面量

       Rust中的整型字面量可以带上一个后缀来指示它的类型,例如,65u8是 u8类型。如果整型字面量没有携带类型后缀,Rust会延迟确定其类型,如果有多个候选类型,且包含i32,则选择 i32,否则报告类型歧义错误。

       前缀 0x0o0b 分别表示十六进制字面量、八进制字面量和二进制字面量。为了易读性,可以在数字之间任意插入下划线,例如,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 学习笔记】Rust 基础数据类型介绍(一)-LMLPHP
       如果浮点字面量缺少类型后缀,那么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_ 后面可以跟着的运算名称如下表所示:



【Rust 学习笔记】Rust 基础数据类型介绍(一)-LMLPHP

12-01 16:11