0x00 回顧
上篇文章咱們介紹了結(jié)構(gòu)體餐塘,結(jié)構(gòu)體類(lèi)型是一種自定義的數(shù)據(jù)類(lèi)型,當(dāng)然也可以把 多個(gè)類(lèi)型組合在一起成為新的類(lèi)型皂吮。本篇文章介紹另一種自定義數(shù)據(jù)類(lèi)型——枚舉(enum)戒傻。一起來(lái)看看它和結(jié)構(gòu)體又有什么區(qū)別吧
0x01 定義
枚舉類(lèi)型是一種自定義的數(shù)據(jù)類(lèi)型,使用 **enum **關(guān)鍵字 + 自定義的命名 + 枚舉值來(lái)定義蜂筹。我們通過(guò)使用 枚舉名 :: 枚舉值 來(lái)訪(fǎng)問(wèn)枚舉的值需纳。使用場(chǎng)景:當(dāng)一個(gè)參數(shù)可能存在多個(gè)取值范圍時(shí),我們定義成枚舉類(lèi)型來(lái)控制變量的取值范圍艺挪,從而防止輸入非法值不翩。示例代碼如下:
// 枚舉示例代碼
// 聲明一個(gè)星期的枚舉類(lèi)型,只有7天麻裳,周一到周日口蝠。
enum Week {
Mon,
Tue,
Wed,
Thu,
Fri,
Sat,
Sun
}
0x02 C 式枚舉
上面的示例代碼,就是Rust中最簡(jiǎn)單的枚舉類(lèi)型了津坑,同 **C 語(yǔ)言 **一模一樣妙蔗。在內(nèi)存中,C 式枚舉的值存儲(chǔ)為整數(shù)疆瑰,默認(rèn)從0開(kāi)始眉反,后面的值依次 +1。如果想更改某個(gè)枚舉的值穆役,需要告訴它用什么整數(shù)寸五。示例代碼如下:
// 為了可以格式化打印枚舉值,需要加入下面這行代碼耿币,具體有關(guān) trait 的知識(shí)將在后面介紹梳杏。
#[derive(Debug)]
enum Week {
Mon,
Tue,
Wed,
Thu = 300,
Fri,
Sat,
Sun
}
fn main() {
// 打印枚舉類(lèi)型
println!("{:?}", Week::Wed);
// 打印枚舉的值
println!("{}", Week::Wed as i32);
println!("{}", Week::Mon as i32);
// 由于Thu 賦值維 300, 則后面的值依次+1
println!("{}", Week::Fri as i32);
}
// 輸出結(jié)果:
// Wed
// 2
// 0
// 301
0x03 包含數(shù)據(jù)的枚舉
在 Rust 中,枚舉的值存在 3 種變體掰读,分別對(duì)應(yīng)前兩篇文章介紹的 3 種結(jié)構(gòu)體秘狞。沒(méi)有數(shù)據(jù)的變體對(duì)應(yīng)類(lèi)基元結(jié)構(gòu)體,元組變體的寫(xiě)法和作用同元組結(jié)構(gòu)體一樣蹈集,結(jié)構(gòu)體變體則存在花括號(hào)和命名字段烁试。在一個(gè)枚舉里可以同時(shí)存在3 種變體。
#[derive(Debug)]
enum Color {
// 定義色值拢肆,參數(shù)分別表示16進(jìn)制顏色代碼减响,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);
// 輸出結(jié)果:
// White("#FFFFFF", 255, 255, 255)
// Red
// Black { code: "#000000", r: 0, g: 0, b: 0 }
}
0x04 枚舉的內(nèi)存布局
我們以 Week 為例支示,來(lái)看下枚舉在內(nèi)存中的布局吧刊橘。廢話(huà)不多說(shuō),先上圖颂鸿,后解釋促绵。
不知道大家能不能看懂呢。首先如果一個(gè)枚舉類(lèi)型存在多個(gè)枚舉值嘴纺,那么它會(huì)為每個(gè)枚舉值分配一個(gè)標(biāo)簽败晴,從0開(kāi)始計(jì)數(shù),占1字節(jié)栽渴。我們每個(gè)枚舉值尖坤,還有3個(gè)u8類(lèi)型的值,每個(gè)類(lèi)型占1字節(jié)闲擦。由于對(duì)齊原因慢味,留空4字節(jié),對(duì)齊8字節(jié)(有關(guān)Rust內(nèi)存對(duì)齊的問(wèn)題墅冷,我找時(shí)間單獨(dú)一篇文章介紹)纯路。最后String占24字節(jié),關(guān)于String的內(nèi)存模型寞忿,我已經(jīng)在前面講過(guò)了感昼。Week 總共占 32 字節(jié)。
最后罐脊,我們通過(guò)編譯器驗(yàn)證下內(nèi)存數(shù)據(jù)。如下圖:
另外蜕琴,如果一個(gè)枚舉類(lèi)型僅存在一個(gè)枚舉值萍桌,那么他不會(huì)存在占一個(gè)字節(jié)的標(biāo)簽。大家可通過(guò)編譯器自行驗(yàn)證凌简。我在這里就不做贅述了上炎。
注:上面的內(nèi)存模型是以 Rust 1.62.1 版本為基礎(chǔ)的。Rust 后續(xù)依然可能會(huì)對(duì)枚舉的內(nèi)存作出優(yōu)化雏搂。
0x05 小結(jié)
枚舉類(lèi)型到這里就介紹完了藕施,其實(shí)枚舉在任何項(xiàng)目中都是很常見(jiàn)的。本篇文章主要介紹了枚舉的定義和內(nèi)存布局凸郑,使用枚舉的是為了必須保證安全的訪(fǎng)問(wèn)數(shù)據(jù)裳食,在某些場(chǎng)景下大概率會(huì)同模式匹配一起使用。
介紹了枚舉類(lèi)型之后芙沥,Rust 常用的數(shù)據(jù)類(lèi)型已經(jīng)介紹完了诲祸。之后的文章將進(jìn)入 Rust 中級(jí)階段浊吏,了解 Rust 的泛型,Trait救氯,所有權(quán)指針等等找田。接下來(lái)的文章將是真正揭開(kāi) Rust 神秘面紗的時(shí)刻。
0x06 本節(jié)源碼
024 · StudyRust - 碼云 - 開(kāi)源中國(guó) (gitee.com)
從下一篇文章開(kāi)始進(jìn)入中級(jí)教程