Memory 枚举和选项的内存表示形式是什么<;枚举>;?

Memory 枚举和选项的内存表示形式是什么<;枚举>;?,memory,rust,Memory,Rust,考虑到以下情况(): Rust如何表示内存中的类型A、Option、B和Option?Rust如何能够将这四种表示都作为单字节表示?选项是有意义的,但我希望选项是两个字节。免责声明:这里看到的确切行为不能保证总是正确的。您不应该依赖于特定的值。此外,该答案仅基于观察结果,且仅针对枚举进行具体说明;其他内存优化围绕&Ts、NonNulls、NonZeroU8s(和系列)以及包含这些优化的嵌套结构而存在 基本枚举 如果您有一个简单的无嵌套结构枚举,默认行为是枚举变量从零开始并向上递增。因此,第一个

考虑到以下情况():

Rust如何表示内存中的类型
A
Option
B
Option
?Rust如何能够将这四种表示都作为单字节表示?
选项
是有意义的,但我希望
选项
是两个字节。

免责声明:这里看到的确切行为不能保证总是正确的。您不应该依赖于特定的值。此外,该答案仅基于观察结果,且仅针对枚举进行具体说明;其他内存优化围绕
&T
s、
NonNull
s、
NonZeroU8
s(和系列)以及包含这些优化的嵌套结构而存在


基本枚举 如果您有一个简单的无嵌套结构枚举,默认行为是枚举变量从零开始并向上递增。因此,第一个不可表示位模式用作
None
值:

enum Simple { A, B };
println!("{}", unsafe { transmute::<Option<Simple>, u8>(None) });
// prints 2
enum ExtendsToEnd { A = 1, B = 255 };
println!("{}", unsafe { transmute::<Option<ExtendsToEnd>, u8>(None) });
// prints 0
如果在前面留有间隙,并且在位空间的末尾有一个变量,只有这样,它才会使用全零作为
None
值:

enum Simple { A, B };
println!("{}", unsafe { transmute::<Option<Simple>, u8>(None) });
// prints 2
enum ExtendsToEnd { A = 1, B = 255 };
println!("{}", unsafe { transmute::<Option<ExtendsToEnd>, u8>(None) });
// prints 0
我的猜测是,编译器不会跟踪所有可表示的位模式,而是只保留用于执行这些检查的范围


更有趣的东西。 如果您的枚举有一个嵌套枚举值的变量,它也会考虑到这一点:

enum Nested { A, B };
enum Complex { A(Nested), B };
println!("{}", unsafe { transmute::<Option<Complex>, u8>(None) });
// prints 3
看看这一切吧


另请参见。

还有,我可以使用什么工具来查找此类信息?我认为您假设“无”的情况必须全部为零。你可以看到一点不安全的记忆转化,让自己幻灭。选项“无”分别编码为3和4。@kmdreko Yikes,这正是我要找的。谢谢“但是,如果两个变量都有值,它似乎会中断”,这是必须的,因为您必须能够获取对内部值的引用,因此它们必须精确地表示为相应的类型,并且编译器不能随意选择类似于
Complex::B
@mcarton中的值,您能详细说明吗?我想我已经构建了
Nested1
Nested2
,这样它们都可以在一个字节
中表示,更复杂的
枚举,而无需修改。哦,对了,那可能就是没人费心实现优化。你拥有合适的条件似乎很少见。
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
enum MyOption<T> { None, Some(T) };
println!("{}", unsafe { transmute::<MyOption<Simple>, u8>(MyOption::None) });
// prints 2