Rust 基础系列 #3: Rust 中的数据类型
现在来讲解数据类型是再自然不过的了。
Rust
现在来讲解数据类型是再自然不过的了。
![](/data/attachment/album/202305/13/215245a1wjvnwtcwawasnw.jpg)


在 [上一篇](/article-15771-1.html) 关于 Rust 编程语言的文章中，我们提到了变量、常量和 <ruby> 遮蔽 <rt>  shadowing </rt></ruby> 。


现在来讲解数据类型是再自然不过的了。


### 数据类型是什么？


将这个词汇展开些单词的顺序改变一下你就会得到答案了；“数据类型” -> “数据的类型”。


计算机使用 `0` 和 `1` 来存储数据，但是为了让数据在读取时有意义，我们使用数据类型来表示这些 `0` 和 `1` 的含义。


Rust 有两种数据类型：


* **标量数据类型**：只能存储单个值的类型。
* **复合数据类型**：可以存储多个值，甚至是不同类型的值。


在本文中，我将讲解标量数据类型。我将在下一篇文章中讲解第二类数据类型。


接下来是 Rust 中四种主要标量数据类型的简要概述：


* **整型**：存储整数。有每种特定情况下使用的子类型。
* **浮点数**：存储带有小数部分的数字。有两种基于大小的子类型。
* **字符**：使用 UTF-8 编码存储单个字符。（是的，你可以在字符中存储表情符号\*。）
* **布尔值**： 存储 `true` 或 `false`。（给那些无法就 `0` 是 `true` 还是 `0` 是 `false` 达成一致的开发者。）


### 整型


在编程语言中，整型指的是一个整数。Rust 中的整型要么是**有符号**的，要么是**无符号**的。无符号整型只能存储 0 和正数，而有符号整型可以存储负数、0 和正数。



> 
> ? 一个有符号整型的范围从 `-(2<sup> n-1</sup>)` 开始，以 `(2<sup> n-1</sup>)-1` 结束。同样，无符号整型的范围从 `0` 开始，以 `(2<sup> n</sup>)-1` 结束。
> 
> 
> 


这是根据符号和长度可用的整型：


![Rust 中的整型数据类型](/data/attachment/album/202305/13/215336o4bb14swb94qzm3w.png)


正如你所见，Rust 有 8、16、32、64 甚至 128 位的有符号和无符号整型！


使用 `*size` 的整型根据计算机的架构而变化。在 8 位微控制器上，它是 `*8`，在 32 位的旧计算机上，它是 `*32`，在现代 64 位系统上，它是 `*64`。


使用 `*size` 是为了存储与内存（这与裸机相关）有关的数据，比如指针、偏移量等。



> 
> ? 当你没有显式地指定整型的子类型时，Rust 编译器会默认推断为 `i32`。显然，如果值比 `i32` 能存储的值大或小，Rust 编译器会礼貌地报错并要求你手动指定类型。
> 
> 
> 


Rust 不仅允许你以十进制形式存储整数，还允许你以二进制、八进制和十六进制形式存储整数。


为了更好的可读性，你可以使用下划线 `_` 来代替逗号来书写/读取大数。



```
fn main() {
    let bin_value = 0b100_0101; // 使用前缀“0b”表示二进制
    let oct_value = 0o105; // 使用前缀“0o”表示八进制
    let hex_value = 0x45; // 使用前缀“0x”表示十六进制
    let dec_value = 1_00_00_000; // 和写一克若（1,00,00,000）一样

    println!("二进制值: {bin_value}");
    println!("八进制值: {oct_value}");
    println!("十六进制值: {hex_value}");
    println!("十进制值: {dec_value}");
}

```

我使用二进制、八进制和十六进制分别将十进制数 69 存储在变量 `bin_value`、`oct_value` 和 `hex_value` 中。在变量 `dec_value` 中，我存储了数字 <ruby> <a href="https://zh.wikipedia.org/zh-cn/%E5%85%8B%E8%8B%A5">  1 克若 </a> <rt>  1 Crore </rt></ruby>（一千万），并且使用了下划线替代逗号，这是印度的书写系统。对于那些更熟悉国际计数系统的人来说，你可以将其写成 `10_000_000`。


在编译并运行这个二进制文件后，我得到了如下输出：



```
二进制值: 69
八进制值: 69
十六进制值: 69
十进制值: 10000000

```

### 浮点数


浮点数是一种存储带有小数部分的数字的数据类型。


与 Rust 中的整型不同，浮点数只有两种子类型：


* `f32`: 单精度浮点数类型
* `f64`: 双精度浮点数类型


和 Rust 中的整型一样，当 Rust 推断一个变量的类型时，如果它看起来像一个浮点数，那么它就会被赋予 `f64` 类型。这是因为 `f64` 类型比 `f32` 类型有更高的精度，并且在大多数计算操作中几乎和 `f32` 类型一样快。请注意，*浮点数据类型（`f32` 和 `f64`）都是**有符号**的*。



> 
> ? Rust 编程语言按照 [IEEE 754](https://zh.wikipedia.org/zh-cn/IEEE_754) 二进制浮点数表示与算术标准存储浮点数。
> 
> 
> 



```
fn main() {
    let pi: f32 = 3.1400; // f32
    let golden_ratio = 1.610000; // f64
    let five = 5.00; // 小数点表示它必须被推断为浮点数
    let six: f64 = 6.; // 尽管类型说明被显式的添加了，小数点也是**必须**的

    println!("pi: {pi}");
    println!("黄金比例: {golden_ratio}");
    println!("五: {five}");
    println!("六: {six}");
}

```

仔细看第 5 行。尽管我已经为变量 `six` 指定了类型，但我**必须**至少加上一个小数点。小数点之后有什么就由你决定了。


程序的输出是相当可预测的... 吗？



```
pi: 3.14
黄金比例: 1.61
五: 5
六: 6

```

在上面的输出中，你可能已经注意到，当显示变量 `pi`、`golden_ratio` 和 `five` 中存储的值时，我在变量声明时在结尾增加的零已经消失了。


就算这些零没有被 *移除*，它们也会在通过 `println` 宏输出值时被省略。所以，不，Rust 没有篡改你的变量值。


### 字符


你可以在一个变量中存储一个字符，类型是 `char`。像 80 年代的传统编程语言一样，你可以存储一个 [ASCII](https://www.ascii-code.com/?ref=itsfoss.com) 字符。但是 Rust 还扩展了字符类型，以存储一个有效的 UTF-8 字符。这意味着你可以在一个字符中存储一个表情符号 ?



> 
> ? 一些表情符号实际上是两个已有表情符号的组合。一个很好的例子是“燃烧的心”表情符号：❤️‍?。这个表情符号是通过使用 [零宽度连接器](https://unicode-table.com/en/200D/?ref=itsfoss.com) 来组合两个表情符号构成的：❤️ + ? = ❤️‍?
> 
> 
> Rust 的字符类型无法存储这样的表情符号。
> 
> 
> 



```
fn main() {
    let a = 'a';
    let p: char = 'p'; // 带有显性类型说明
    let crab = '?';

    println!("Oh look, {} {}! :{}", a, crab, p);
}

```

正如你所见，我已经将 ASCII 字符 'a' 和 'p' 存储在变量 `a` 和 `p` 中。我还在变量 `crab` 中存储了一个有效的 UTF-8 字符，即螃蟹表情符号。然后我打印了存储在每个变量中的字符。


这是输出：



```
Oh look, a ?! :p

```

### 布尔值


在 Rust 中，布尔值类型只存储两个可能的值之一：`true` 或 `false`。如果你想显性指定类型，请使用 `bool`。



```
fn main() {
    let val_t: bool = true;
    let val_f = false;

    println!("val_t: {val_t}");
    println!("val_f: {val_f}");
}

```

编译并执行上述代码后，结果如下：



```
val_t: true
val_f: false

```

### 额外内容：显性类型转换


在上一篇讲述 Rust 编程语言中的变量的文章中，我展示了一个非常基础的 [温度转换程序](/article-15771-1.html)。在那里，我提到 Rust 不允许隐式类型转换。


但这不代表 Rust 也不允许 *显性* 类型转换 ; )


要进行显性类型转换，使用 `as` 关键字，后面跟着要转换的数据类型。


这是一个示例程序：



```
fn main() {
    let a = 3 as f64; // f64
    let b = 3.14159265359 as i32; // i32

    println!("a: {a}");
    println!("b: {b}");
}

```

在第二行，我没有使用 `3.0`，而是在 `3` 后面写上 `as f64`，以表示我希望编译器将 `3`（一个整数）转换为 64 位浮点数的类型转换。第三行也是一样。但是这里，类型转换是**有损的**。这意味着小数部分 *完全消失*。它不是存储为 `3.14159265359`，而是存储为简单的 `3`。


程序的输出可以验证这一点：



```
a: 3
b: 3

```

### 总结


本文介绍了 Rust 中的原始/标量数据类型。主要有四种这样的数据类型：整型、浮点数、字符和布尔值。


整型用于存储整数，它们有几种子类型，基于它们是有符号还是无符号以及长度。浮点数用于存储带有小数的数字，根据长度有两种子类型。字符数据类型用于存储单个有效的 UTF-8 编码字符。最后，布尔值用于存储 `true` 或 `false` 值。


在下一章中，我将讨论数组和元组等复合数据类型。敬请关注。


*（题图：MJ/c0c49e15-cc9d-4eef-8e52-2f0d62294965）*




---


via: <https://itsfoss.com/rust-data-types/>


作者：[Pratham Patel](https://itsfoss.com/author/pratham/) 选题：[lkxed](https://github.com/lkxed/) 译者：[Cubik65536](https://github.com/Cubik65536) 校对：[wxy](https://github.com/wxy)


本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译，[Linux中国](https://linux.cn/) 荣誉推出

