2023-05-11 23:09:27 +08:00
|
|
|
|
[#]: subject: "Rust Basics Series #3: Data Types in Rust"
|
|
|
|
|
[#]: via: "https://itsfoss.com/rust-data-types/"
|
|
|
|
|
[#]: author: "Pratham Patel https://itsfoss.com/author/pratham/"
|
|
|
|
|
[#]: collector: "lkxed"
|
|
|
|
|
[#]: translator: "Cubik65536"
|
2023-05-13 21:54:22 +08:00
|
|
|
|
[#]: reviewer: "wxy"
|
|
|
|
|
[#]: publisher: "wxy"
|
|
|
|
|
[#]: url: "https://linux.cn/article-15811-1.html"
|
2023-05-11 23:09:27 +08:00
|
|
|
|
|
|
|
|
|
Rust 基础系列 #3: Rust 中的数据类型
|
|
|
|
|
======
|
|
|
|
|
|
2023-05-13 21:54:22 +08:00
|
|
|
|
![][0]
|
2023-05-11 23:09:27 +08:00
|
|
|
|
|
|
|
|
|
在 [上一篇](https://linux.cn/article-15771-1.html) 关于 Rust 编程语言的文章中,我们提到了变量、常量和 <ruby>遮蔽<rt>shadowing</rt></ruby> 。
|
|
|
|
|
|
|
|
|
|
现在来讲解数据类型是再自然不过的了。
|
|
|
|
|
|
|
|
|
|
### 数据类型是什么?
|
|
|
|
|
|
2023-05-13 21:54:22 +08:00
|
|
|
|
将这个词汇展开些单词的顺序改变一下你就会得到答案了;“数据类型” -> “数据的类型”。
|
2023-05-11 23:09:27 +08:00
|
|
|
|
|
|
|
|
|
计算机使用 `0` 和 `1` 来存储数据,但是为了让数据在读取时有意义,我们使用数据类型来表示这些 `0` 和 `1` 的含义。
|
|
|
|
|
|
|
|
|
|
Rust 有两种数据类型:
|
|
|
|
|
|
|
|
|
|
- **标量数据类型**:只能存储单个值的类型。
|
|
|
|
|
- **复合数据类型**:可以存储多个值,甚至是不同类型的值。
|
|
|
|
|
|
|
|
|
|
在本文中,我将讲解标量数据类型。我将在下一篇文章中讲解第二类数据类型。
|
|
|
|
|
|
|
|
|
|
接下来是 Rust 中四种主要标量数据类型的简要概述:
|
|
|
|
|
|
2023-05-13 21:54:22 +08:00
|
|
|
|
- **整型**:存储整数。有每种特定情况下使用的子类型。
|
2023-05-11 23:09:27 +08:00
|
|
|
|
- **浮点数**:存储带有小数部分的数字。有两种基于大小的子类型。
|
|
|
|
|
- **字符**:使用 UTF-8 编码存储单个字符。(是的,你可以在字符中存储表情符号*。)
|
|
|
|
|
- **布尔值**: 存储 `true` 或 `false`。(给那些无法就 `0` 是 `true` 还是 `0` 是 `false` 达成一致的开发者。)
|
|
|
|
|
|
|
|
|
|
### 整型
|
|
|
|
|
|
|
|
|
|
在编程语言中,整型指的是一个整数。Rust 中的整型要么是**有符号**的,要么是**无符号**的。无符号整型只能存储 0 和正数,而有符号整型可以存储负数、0 和正数。
|
|
|
|
|
|
|
|
|
|
> 💡 一个有符号整型的范围从 <code>-(2<sup>n-1</sup>)</code> 开始,以 <code>(2<sup>n-1</sup>)-1</code> 结束。同样,无符号整型的范围从 `0` 开始,以 <code>(2<sup>n</sup>)-1</code> 结束。
|
|
|
|
|
|
|
|
|
|
这是根据符号和长度可用的整型:
|
|
|
|
|
|
|
|
|
|
![Rust 中的整型数据类型][3]
|
|
|
|
|
|
|
|
|
|
正如你所见,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”表示十六进制
|
2023-05-13 21:54:22 +08:00
|
|
|
|
let dec_value = 1_00_00_000; // 和写一克若(1,00,00,000)一样
|
2023-05-11 23:09:27 +08:00
|
|
|
|
|
|
|
|
|
println!("二进制值: {bin_value}");
|
|
|
|
|
println!("八进制值: {oct_value}");
|
|
|
|
|
println!("十六进制值: {hex_value}");
|
|
|
|
|
println!("十进制值: {dec_value}");
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
2023-05-13 21:54:22 +08:00
|
|
|
|
我使用二进制、八进制和十六进制分别将十进制数 69 存储在变量 `bin_value`、`oct_value` 和 `hex_value` 中。在变量 `dec_value` 中,我存储了数字 <ruby>[1 克若][4]<rt>1 Crore</rt></ruby>(一千万),并且使用了下划线替代逗号,这是印度的书写系统。对于那些更熟悉国际计数系统的人来说,你可以将其写成 `10_000_000`。
|
2023-05-11 23:09:27 +08:00
|
|
|
|
|
|
|
|
|
在编译并运行这个二进制文件后,我得到了如下输出:
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
二进制值: 69
|
|
|
|
|
八进制值: 69
|
|
|
|
|
十六进制值: 69
|
|
|
|
|
十进制值: 10000000
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### 浮点数
|
|
|
|
|
|
|
|
|
|
浮点数是一种存储带有小数部分的数字的数据类型。
|
|
|
|
|
|
|
|
|
|
与 Rust 中的整型不同,浮点数只有两种子类型:
|
|
|
|
|
|
|
|
|
|
- `f32`: 单精度浮点数类型
|
|
|
|
|
- `f64`: 双精度浮点数类型
|
|
|
|
|
|
|
|
|
|
和 Rust 中的整型一样,当 Rust 推断一个变量的类型时,如果它看起来像一个浮点数,那么它就会被赋予 `f64` 类型。这是因为 `f64` 类型比 `f32` 类型有更高的精度,并且在大多数计算操作中几乎和 `f32` 类型一样快。请注意,_浮点数据类型(`f32` 和 `f64`)都是**有符号**的_。
|
|
|
|
|
|
|
|
|
|
> 📋 Rust 编程语言按照 [IEEE 754][5] 二进制浮点数表示与算术标准存储浮点数。
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
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][6] 字符。但是 Rust 还扩展了字符类型,以存储一个有效的 UTF-8 字符。这意味着你可以在一个字符中存储一个表情符号 😉
|
|
|
|
|
|
|
|
|
|
> 💡 一些表情符号实际上是两个已有表情符号的组合。一个很好的例子是“燃烧的心”表情符号:❤️🔥。这个表情符号是通过使用 [零宽度连接器][7] 来组合两个表情符号构成的:❤️ + 🔥 = ❤️🔥
|
|
|
|
|
>
|
|
|
|
|
> 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
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### 额外内容:显性类型转换
|
|
|
|
|
|
2023-05-13 21:54:22 +08:00
|
|
|
|
在上一篇讲述 Rust 编程语言中的变量的文章中,我展示了一个非常基础的 [温度转换程序][8]。在那里,我提到 Rust 不允许隐式类型转换。
|
2023-05-11 23:09:27 +08:00
|
|
|
|
|
2023-05-13 21:54:22 +08:00
|
|
|
|
但这不代表 Rust 也不允许 _显性_ 类型转换 ; )
|
2023-05-11 23:09:27 +08:00
|
|
|
|
|
|
|
|
|
要进行显性类型转换,使用 `as` 关键字,后面跟着要转换的数据类型。
|
|
|
|
|
|
|
|
|
|
这是一个示例程序:
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
fn main() {
|
|
|
|
|
let a = 3 as f64; // f64
|
|
|
|
|
let b = 3.14159265359 as i32; // i32
|
|
|
|
|
|
|
|
|
|
println!("a: {a}");
|
|
|
|
|
println!("b: {b}");
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
2023-05-13 21:54:22 +08:00
|
|
|
|
在第二行,我没有使用 `3.0`,而是在 `3` 后面写上 `as f64`,以表示我希望编译器将 `3`(一个整数)转换为 64 位浮点数的类型转换。第三行也是一样。但是这里,类型转换是**有损的**。这意味着小数部分 _完全消失_。它不是存储为 `3.14159265359`,而是存储为简单的 `3`。
|
2023-05-11 23:09:27 +08:00
|
|
|
|
|
|
|
|
|
程序的输出可以验证这一点:
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
a: 3
|
|
|
|
|
b: 3
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### 总结
|
|
|
|
|
|
2023-05-13 21:54:22 +08:00
|
|
|
|
本文介绍了 Rust 中的原始/标量数据类型。主要有四种这样的数据类型:整型、浮点数、字符和布尔值。
|
2023-05-11 23:09:27 +08:00
|
|
|
|
|
|
|
|
|
整型用于存储整数,它们有几种子类型,基于它们是有符号还是无符号以及长度。浮点数用于存储带有小数的数字,根据长度有两种子类型。字符数据类型用于存储单个有效的 UTF-8 编码字符。最后,布尔值用于存储 `true` 或 `false` 值。
|
|
|
|
|
|
|
|
|
|
在下一章中,我将讨论数组和元组等复合数据类型。敬请关注。
|
|
|
|
|
|
2023-05-13 21:54:22 +08:00
|
|
|
|
*(题图:MJ/c0c49e15-cc9d-4eef-8e52-2f0d62294965)*
|
|
|
|
|
|
2023-05-11 23:09:27 +08:00
|
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
via: https://itsfoss.com/rust-data-types/
|
|
|
|
|
|
|
|
|
|
作者:[Pratham Patel][a]
|
|
|
|
|
选题:[lkxed][b]
|
|
|
|
|
译者:[Cubik65536](https://github.com/Cubik65536)
|
2023-05-13 21:54:22 +08:00
|
|
|
|
校对:[wxy](https://github.com/wxy)
|
2023-05-11 23:09:27 +08:00
|
|
|
|
|
|
|
|
|
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
|
|
|
|
|
|
|
|
|
[a]: https://itsfoss.com/author/pratham/
|
|
|
|
|
[b]: https://github.com/lkxed/
|
|
|
|
|
[1]: https://itsfoss.com/content/images/2023/04/humble-bundle-packt-offer.webp
|
|
|
|
|
[2]: https://itsfoss.com/rust-variables
|
|
|
|
|
[3]: https://media.discordapp.net/attachments/1001332168506753024/1062952929734164540/data-type-table1.png
|
|
|
|
|
[4]: https://zh.wikipedia.org/zh-cn/克若
|
|
|
|
|
[5]: https://zh.wikipedia.org/zh-cn/IEEE_754
|
|
|
|
|
[6]: https://www.ascii-code.com/?ref=itsfoss.com
|
|
|
|
|
[7]: https://unicode-table.com/en/200D/?ref=itsfoss.com
|
|
|
|
|
[8]: https://linux.cn/article-15771-1.html
|
2023-05-13 21:54:22 +08:00
|
|
|
|
[0]: https://img.linux.net.cn/data/attachment/album/202305/13/215245a1wjvnwtcwawasnw.jpg
|