memory - enum和Option的内存表示是什么?
问题描述
鉴于以下(游乐场):
enum A { A = 0, B, C }
enum B { A = 1, B, C }
Rust 如何表示内存中的类型A
、、Option<A>
和?Rust 如何能够将所有这四个都作为单字节表示?这是有道理的,但我预计是两个字节。B
Option<B>
Option<B>
Option<A>
解决方案
免责声明:不能保证此处看到的确切行为将始终成立。您不应该依赖特定的值。此外,这个答案仅基于观察,并且只会专门针对枚举;&T
围绕s、NonNull<T>
s、NonZeroU8
s(和 family)以及包含这些的嵌套结构存在其他内存优化。
基本枚举
如果您有一个简单的非嵌套结构枚举,则默认行为是枚举变量从零开始并向上递增。所以第一个不可表示的位模式被用作None
值:
enum Simple { A, B };
println!("{}", unsafe { transmute::<Option<Simple>, u8>(None) });
// prints 2
如果您的简单非嵌套结构枚举在前面留下一个间隙,则该None
值仍将由枚举变体表示之后的第一个不可表示的位模式表示:
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
在操场上看到这一切。
推荐阅读
- javascript - 将数据从 v-for 解析成一个方法给了我 undefined
- c# - EF Core TPH,获取基本实体时忽略鉴别器
- html - 更改字体颜色后在表格中清空 td (R)
- java - 将浮点数表示为十六进制
- javascript - 在发布请求 Angular 9 后显示引导警报成功
- spring-security - 集成 Swagger 和以前工作的代码中断:无法从 Object 值反序列化(没有基于委托或属性的 Creator
- chronicle-map - ChronicleMap Recovery with multi process application
- java - Get specific value from JSON array using java
- javascript - Export button in datatable does not take filters into consideration
- c - C中如何根据hwnd获取进程名