给定以下(playground):
enum A { A = 0, B, C }
enum B { A = 1, B, C }
Rust如何在内存中表示类型A、Option、B和Option?Rust如何将这四种类型都表示为单字节呢?对于Option来说是有道理的,但我预期Option应该占用两个字节。
给定以下(playground):
enum A { A = 0, B, C }
enum B { A = 1, B, C }
enum Simple { A, B };
println!("{}", unsafe { transmute::<Option<Simple>, u8>(None) });
// prints 2
enum GapInFront { A = 1, B };
println!("{}", unsafe { transmute::<Option<GapInFront>, u8>(None) });
// prints 3
None
值。enum ExtendsToEnd { A = 1, B = 255 };
println!("{}", unsafe { transmute::<Option<ExtendsToEnd>, u8>(None) });
// prints 0
需要注意的一点是,它永远不会在None
值的变体之间选择表示形式。即使存在大量不可表示的位模式,占据边界的变体也会导致它使用2字节:
enum Full { A = 0, B = 255 };
println!("{:?}", unsafe { transmute::<Option<Full>, [u8; 2]>(None) });
// prints [0, 60], which I believe is undefined behavior
// since I think the second byte is left uninitialized
我的猜测是编译器并不跟踪所有可表示的位模式,而仅保留用于执行这些检查的范围。
如果您的枚举类型具有嵌套枚举值的变量,则它也会考虑到该变量:
enum Nested { A, B };
enum Complex { A(Nested), B };
println!("{}", unsafe { transmute::<Option<Complex>, u8>(None) });
// prints 3
enum Nested1 { A, B };
enum Nested2 { A=2, B };
enum MoreComplex { A(Nested1), B(Nested2) };
println!("{:?}", unsafe { transmute::<Option<MoreComplex>, [u8; 2]>(None) });
// prints [2, 211], again the second byte is left uninitialized
另外需要指出的是,这并不是Option
特有的情况;如果您定义了自己的选项类型,则其行为相同:
enum MyOption<T> { None, Some(T) };
println!("{}", unsafe { transmute::<MyOption<Simple>, u8>(MyOption::None) });
// prints 2
在playground上查看此内容。
另请参阅Rust的Option类型的开销是多少?。
Nested1
和Nested2
,以便它们可能都可以在单个字节的MoreComplex
枚举中表示,而不需要进行修改。 - kmdreko