【RUST学习日记】第24课 枚举(Enum)

简介: 【RUST学习日记】第24课 枚举(Enum)

0x00 回顾


上篇文章咱们介绍了结构体,结构体类型是一种自定义的数据类型,当然也可以把 多个类型组合在一起成为新的类型。本篇文章介绍另一种自定义数据类型——枚举(enum)。一起来看看它和结构体又有什么区别吧


0x01 定义


枚举类型是一种自定义的数据类型,使用 **enum **关键字 + 自定义的命名 + 枚举值来定义。我们通过使用 枚举名 :: 枚举值 来访问枚举的值。使用场景:当一个参数可能存在多个取值范围时,我们定义成枚举类型来控制变量的取值范围,从而防止输入非法值。示例代码如下:

// 枚举示例代码// 声明一个星期的枚举类型,只有7天,周一到周日。
enum Week {
    Mon,
    Tue,
    Wed,
    Thu,
    Fri,
    Sat,
    Sun
}


0x02 C 式枚举


上面的示例代码,就是Rust中最简单的枚举类型了,同 C 语言 一模一样。在内存中,C 式枚举的值存储为整数,默认从0开始,后面的值依次 +1。如果想更改某个枚举的值,需要告诉它用什么整数。示例代码如下:

// 为了可以格式化打印枚举值,需要加入下面这行代码,具体有关 trait 的知识将在后面介绍。
#[derive(Debug)]enum Week {
    Mon,
    Tue,
    Wed,
    Thu = 300,
    Fri,
    Sat,
    Sun}fn main() {
    // 打印枚举类型
    println!("{:?}", Week::Wed);
    // 打印枚举的值
    println!("{}", Week::Wed as i32);
    println!("{}", Week::Mon as i32);
    // 由于Thu 赋值维 300, 则后面的值依次+1
    println!("{}", Week::Fri as i32);
}
// 输出结果:
// Wed
// 2
// 0
// 301


0x03 包含数据的枚举


在 Rust 中,枚举的值存在 3 种变体,分别对应前两篇文章介绍的 3 种结构体。没有数据的变体对应类基元结构体,元组变体的写法和作用同元组结构体一样,结构体变体则存在花括号和命名字段。在一个枚举里可以同时存在3 种变体。


#[derive(Debug)]
enum Color {
    // 定义色值,参数分别表示16进制颜色代码,R,G,B
    White(String, u8, u8, u8),
    Red,
    Black { code: String, r: u8, g: u8, b: u8 },
}
fn main() {
    let white = Color::White(String::from("#FFFFFF"), 255, 255, 255);
    let red = Color::Red;
    let black = Color::Black { 
                    code: String::from("#000000"), 
                    r: 0, 
                    g: 0, 
                    b: 0
                 };
    println!("{:?}", white);
    println!("{:?}", red);
    println!("{:?}", black);   
    // 输出结果:
    // White("#FFFFFF", 255, 255, 255)
    // Red
    // Black { code: "#000000", r: 0, g: 0, b: 0 }
}


0x04 枚举的内存布局


我们以 Week 为例,来看下枚举在内存中的布局吧。废话不多说,先上图,后解释。


0a2653c851af460fa595bd959398a8f1.png


不知道大家能不能看懂呢。首先如果一个枚举类型存在多个枚举值,那么它会为每个枚举值分配一个标签,从0开始计数,占1字节。我们每个枚举值,还有3个u8类型的值,每个类型占1字节。由于对齐原因,留空4字节,对齐8字节(有关Rust内存对齐的问题,我找时间单独一篇文章介绍)。最后String占24字节,关于String的内存模型,我已经在前面讲过了。Week 总共占 32 字节

最后,我们通过编译器验证下内存数据。如下图:


2d65d23f6d4748949b924e4057485923.png


另外,如果一个枚举类型仅存在一个枚举值,那么他不会存在占一个字节的标签。大家可通过编译器自行验证。我在这里就不做赘述了。

注:上面的内存模型是以 Rust 1.62.1 版本为基础的。Rust 后续依然可能会对枚举的内存作出优化。


0x05 小结


枚举类型到这里就介绍完了,其实枚举在任何项目中都是很常见的。本篇文章主要介绍了枚举的定义和内存布局,使用枚举的是为了必须保证安全的访问数据,在某些场景下大概率会同模式匹配一起使用。


介绍了枚举类型之后,Rust 常用的数据类型已经介绍完了。之后的文章将进入 Rust 中级阶段,了解 Rust 的泛型,Trait,所有权指针等等。接下来的文章将是真正揭开 Rust 神秘面纱的时刻。

相关文章
|
4月前
|
Rust 安全 网络协议
Rust 笔记:Rust 语言中的枚举 与 模式匹配
Rust 笔记:Rust 语言中的枚举 与 模式匹配
68 0
|
22天前
|
Rust 安全 C++
30天拿下Rust之枚举
Rust中的枚举是一种用户定义的类型,它允许你为一组相关的值赋予友好的名称。在Rust中,枚举是强大的工具,它们不仅仅用于表示几个固定的值,还可以包含函数和方法,使得枚举成员可以有自己的行为。通过与模式匹配和其他Rust特性结合使用,枚举在构建健壮、无崩溃的应用程序中发挥了重要作用,并可大幅提高代码的可读性、可维护性和类型安全性。
40 10
|
10天前
|
Rust Linux Go
Rust/Go语言学习
Rust/Go语言学习
|
1月前
|
存储 Rust 安全
【Rust学习】06_切片
所有权、借用和切片的概念确保了 Rust 程序在编译时的内存安全。Rust 语言提供了跟其他系统编程语言相同的方式来控制你使用的内存,但拥有数据所有者在离开作用域后自动清除其数据的功能意味着你无须额外编写和调试相关的控制代码。
18 1
|
2月前
|
存储 Rust 安全
【Rust学习】04_所有权
所有权是 Rust 最独特的特性,对语言的其余部分有着深远的影响。它使 Rust 能够在不需要垃圾收集器的情况下保证内存安全,因此了解所有权的运作方式非常重要。在本章中,我们将讨论所有权以及几个相关功能:借用、切片以及 Rust 如何在内存中布局数据。
17 1
|
2月前
|
存储 Rust 编译器
【Rust学习】03_通用编程概念
您成功了!这是一个相当大的章节:您了解了变量、标量和复合数据类型、函数、注释、 if 表达式和循环!若要练习本章中讨论的概念。
26 2
|
2月前
|
Rust 编译器
【Rust学习】05_引用和借用
在这章我们将开始学习Rust的引用和借用,它们是Rust中重要的概念,它们允许我们创建可变引用,以及创建不可变引用。
17 0
|
3月前
|
Rust Linux iOS开发
【Rust学习】01_入门准备
让我们开始您的 Rust 之旅吧!有很多东西要学,但每一段旅程都是从第一步开始的,在本章中,我们将一起来学习以下知识点: - 在 Linux、macOS 和 Windows 上安装 Rust - 编写打印程序 Hello, world! - 使用 cargo Rust 的包管理器和构建系统
68 1
|
3月前
|
存储 移动开发 Rust
【Rust学习】02_猜谜游戏
让我们一起动手完成一个项目,来快速上手 Rust!本章将介绍 Rust 中一些常用概念,并向您展示如何在实际项目中运用它们。您将会学到 let、match、方法、关联函数、引用外部 crate 等知识!后续章节会深入探讨这些概念的细节。
28 0
|
4月前
|
Rust 安全 算法
【深入探索Rust:结构体、枚举与模式匹配】A Deep Dive into Rust: Structs, Enums, and Pattern Matching
【深入探索Rust:结构体、枚举与模式匹配】A Deep Dive into Rust: Structs, Enums, and Pattern Matching
76 0
【深入探索Rust:结构体、枚举与模式匹配】A Deep Dive into Rust: Structs, Enums, and Pattern Matching