likes
comments
collection
share

Rust 入门实战系列(4)- 基础数据类型

作者站长头像
站长
· 阅读数 20

今天我们来学习数据类型

Rust 是一门静态类型的语言,在编译期就需要知道所有变量的类型。很多时候编译期可以推断出来我们给出的值对应的类型,即便我们没有声明。类似我们此前提过的 let x = 5;。但这种推断能力也不是万能的,有时候一个场景下可能有多个类型都适用。这个时候编译器就会报错,要求我们提供更多信息来辅助判断。

比如下面这个例子:

let guess: u32 = "42".parse().expect("Not a number!");

这里又是上一节在 Guessing Game 里我们遇到过的 parse 函数,还记得么? 它能够将 string 转 number,但同时要注意,parse 是个很通用的函数,事实上任何一个实现了 FromStr 这个 trait 的类型,都可以作为 parse 的返回值。详细的说明大家参考下面文档就 ok。这里我们只用知道,它的返回值很多样,我们需要指明类型,否则编译器区分不出来。

Rust 入门实战系列(4)- 基础数据类型

如果我们不加 u32,看看会怎么样。

(注:这一节的相关代码在 rust-learn 的 datatype 目录下)

fn main(){
    let _guess = "42".parse().expect("Not a number!");
}

运行之后编译器给出报错:

$ cargo build
========================================
   Compiling datatype v0.1.0 (/Users/ag9920/go/src/github.com/ag9920/rust-learn/datatype)
error[E0282]: type annotations needed
 --> src/main.rs:2:9
  |
2 |     let _guess = "42".parse().expect("Not a number!");
  |         ^^^^^^
  |
help: consider giving `_guess` an explicit type
  |
2 |     let _guess: _ = "42".parse().expect("Not a number!");
  |               +++

For more information about this error, try `rustc --explain E0282`.
error: could not compile `datatype` due to previous error

好了,这里只是个示例,我们知道了类型的重要性。Rust 的类型大体上可以分为两类:标量(scalar), 复合(compound),今天我们先来了解一下标量,下一节我们再来学习复合类型。

一个标量代表了单独的一个值,其实就是我们一般说的【基础数据类型】,Rust 的标量跟其他语言基本一样,大体上分为 4 类:

  • 整型 integer
  • 浮点数 floating-point number
  • 布尔 bool
  • 字符 character

整型

我们此前使用过 u32 这个整型,这里也可以看出 Rust 也是区分有符号和无符号的,就看是否单拎出来一个符号位放在最高位。事实上 Rust 默认的整型类型是 i32。

Rust 支持的整型类型如下图:

Rust 入门实战系列(4)- 基础数据类型

无符号意味着永远大于等于0,有符号的整数则是用经典的 two's complement 来表示,翻译成中文叫做【整数二进制补码】。

To get the two's complement negative notation of an integer, you write out the number in binary. You then invert the digits, and add one to the result.

强烈建议对补码不了解的同学读一下这篇文章:Two's Complement,笔者在 CMU 上学时的第一课就是学习 Two's Complement 如何来表示负数。这里我们只提一下要点:

  • 二进制最高位如果为 1,代表负数,如果为 0,代表这个数 >= 0;
  • 要拿到一个正数所对应的负数,可以将其用二进制写出来,然后把每个位取反,最后给结果加上 1。

有了 Two's Complement,一切减法都变成了加法。简单的【取反+1】就可以搞定。

无符号整数因为少了一个符号位,可以用所有的位来表示数字。比如 u8 一共有 8位,那么它的取值范围就是 0 到 2 的 8 次方 - 1(总共 2 的 8 次方个数),也就是 [0, 255]。而如果是有符号整数,支持了负数,所以取值范围变成了 负的 2 的 7次方 到 正的 2 的 7次方 -1,也就是 [-128, 127]。

其实很简单,总共 n 个 bit,说破大天去也最多表示 2 的 n 次方个值,还得包括 0. 所以,大家记住这一点就好:0 和正数是一类,负数自己是一类。两类可表示的数字的数量一定是相等的。

还有一个点大家可能会不理解,这个 isize 和 usize 是个什么鬼?

其实,这两个类型取决于运行 Rust 项目的计算机架构,所以前面标注了 arch。什么意思呢?如果你在基于 64 位的架构上跑,那么 isize 和 usize 就占 64 位,如果你在 32 位的架构上跑,那这俩就占 32 位。

除此之外,Rust 也支持了一些字面量,比如 1_000 同样代表 1000,只是为了便于理解:

Rust 入门实战系列(4)- 基础数据类型

这里还有我们常用的 0x 代表 16进制,0o 代表 8进制,大家混个眼熟即可。

浮点数

Rust 支持两种浮点数类型: f32 和 f64,前者占用 32 位,后者 64 位。二者速度几乎相同,而 f64 支持更高的精读,所以 Rust 默认的浮点类型是 f64。

和整型不同,所有浮点型都是【有符号的】。我们来看一个例子。

fn main() {
    let x = 2.0; // f64

    let y: f32 = 3.0; // f32
}

Rust 的浮点数遵循 IEEE 754 标准 , 这是 20世纪80年代依赖最广泛使用的浮点数运算标准,f32 对应单精度,f64 对应双精度。

数值计算

Rust 支持基本的数学计算,加减乘除和取模。其中整数除法将会取最接近的整数。下面我们来看看怎么操作:

fn main() {
    // addition
    let sum = 5 + 10;

    // subtraction
    let difference = 95.5 - 4.3;

    // multiplication
    let product = 4 * 30;

    // division
    let quotient = 56.7 / 32.2;
    let floored = 2 / 3; // Results in 0

    // remainder
    let remainder = 43 % 5;
}

非常简单直接,跟其他语言一样,这些基础的不用多说。Rust 支持的运算符远不止这几种,参照官方运算符

Rust 入门实战系列(4)- 基础数据类型

后面还有很多,需要查阅的同学直接点击上面链接进去即可。

布尔类型

和其他大多数语言一样,Rust 的布尔也支持 truefalse 两种。布尔类型空间上占用一个字节,8位。

fn main() {
    let t = true;

    let f: bool = false; // with explicit type annotation
}

声明起来也非常简单,这里不再赘述。

字符类型

Rust 的 char 类型和 C 语言的一样,都代表了一个字符。

fn main() {
    let c = 'z';
    let z: char = 'ℤ'; // with explicit type annotation
    let heart_eyed_cat = '😻';
}

我们可以直接让编译器来推断,也可以显式地指明类型。

  • char 用的是单引号,而 string 类型用的则是双引号;
  • char 类型占用 4 个字节,代表了一个 Unicode 标量值,即 除去高位代理和低位代理之外,所有的Unicode码位,也就是U+0000~U+D7FF和U+E000~U+10FFFF范围内的码位。这也意味着它可以比 ASCII 码强大的多,包括中文,日文,韩文,表情符都可以,不可见字符也是合法的 char

需要注意的是,char 虽然是 character 的缩写,但正如计算机语言中的浮点数和真实算术中的小数不能划等号一样,char 的规范和常规意义上一个字符也是不等价的,用之前一定要注意。

小结

今天我们了解了 Rust 中四种基本数据类型:integer, floating-pointer number, bool, char。其实整体上和 C 语言差别不大,大家就当复习一下,这些类型我们日后会经常用到,大家此时混个脸熟就 ok。

下一篇我们来了解 Rust 中的复合类型(compound)。

感谢阅读!欢迎一起成长!