Skip to content

Rust数据类型

基本数据类型

整数类型

长度 有符号类型 无符号类型
8位 i8 u8
16位 i16 u16
32位 i32 u32
64位 i64 u64
128位 i128 u128
依赖平台(x64/x86) isize usize

绑定一个整形变量时,默认使用i32类型。

整型溢出

以u8为例,范围是0~255,如果运算时结果超过这个范围就会发生溢出。

针对溢出,Rust标准库提供了以下几种显式处理方式:

lang/rust/data-type | vglab

  • wrapping_* 方法在所有模式下都按照补码循环溢出规则处理,例如 wrapping_add

  • 如果使用 checked_* 方法时发生溢出,则返回 None 值

  • overflowing_* 方法返回该值和一个指示是否存在溢出的布尔值

  • saturating_* 方法,可以限定计算后的结果不超过目标类型的最大值或低于最小值

浮点类型

浮点数操作的陷阱

基于浮点数的底层表示,浮点数操作通常需要注意两点:

  • 浮点数的近似问题:由于浮点数的表示方式,某些十进制数无法精确表示为二进制浮点数,这可能导致计算结果出现微小的误差。例如,0.1在二进制中是一个无限循环小数,因此在计算时可能会得到一个近似值而不是精确的0.1。

    lang/rust/data-type | vglab

  • 浮点数在某些特性上是反直觉的1:比方说在比较上,因为 f32f64 上的比较运算实现的是 std::cmp::PartialEq 特征(类似其他语言的接口),但是并没有实现 std::cmp::Eq 特征,但是后者在其它数值类型上都有定义;在这样的差别下,如果还想当然的凭直觉直接比较,会带来很多意想不到的错误。

    HashMap1

    Rust 的 HashMap 数据结构,是一个 KV 类型的 Hash Map 实现,它对于 K 没有特定类型的限制,但是要求能用作 K 的类型必须实现了 std::cmp::Eq 特征,因此这意味着你无法使用浮点数作为 HashMap 的 Key,来存储键值对,但是作为对比,Rust 的整数类型、字符串类型、布尔类型都实现了该特征,因此可以作为 HashMap 的 Key。

浮点数操作准则

针对上面提到的两个问题,在使用浮点数进行运算时,需要遵循以下准则:

  • 避免在浮点数上测试相等性

  • 当结果在数学上可能存在未定义时,需要格外的小心

NaN

NaN(Not a Number)是一个特殊的浮点数值,表示未定义或不可表示的结果,例如0除以0、无穷大减去无穷大、负数开平方等操作都会产生NaN。

NaN具有以下特点:

  • NaN不等于任何值,包括它自己。这意味着NaN不能用于比较。若尝试比较NaN与任何值(包括NaN本身),结果总是返回false。

    thread 'main' (61907) panicked at src/main.rs:50:5:
    assertion failed: f64::NAN == f64::NAN
    note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
    
  • 所有跟NaN相关的操作都会返回NaN

Rust By Practice

数值类型 | Rust By Practice( Rust 练习实践 )

其他数据类型

布尔类型

字符类型

在 Rust 中,字符类型 char 是一个 Unicode 标量值,占用 4 字节(32 位)。它可以表示任何 Unicode 字符,包括 ASCII 字符、汉字、表情符号等。Rust 的 char 类型使用单引号 ' 来表示。

也就是说,下面的这些都是合法的 Rust 字符:

fn main() {
    let c = 'z';
    let z = 'ℤ';
    let g = '国';
    let heart_eyed_cat = '😻';
}

单元类型

单元类型只有一个值,即(),用于表示空值或无意义的值,在内存中占用0个字节,可以用作一个值来占位。

在Rust中,main 函数是有返回值,且其返回值就是单元类型(println!() 的返回值也是 ())。

发散函数

没有返回值的函数在 Rust 中是有单独的定义的:发散函数( diverging functions )(-> !),顾名思义,无法收敛的函数。