为什么只有一个必要时,Rust用两个字节来表示这个枚举?

时间:2019-02-03 01:32:02

标签: enums rust memory-layout

即使只有8 * 8 = 64的可能性,它似乎也足够聪明,仅对A使用一个字节,而对于对B使用一个字节则不够聪明。有什么办法哄骗Rust解决这个问题,还是我必须手动实现更紧凑的布局?

Playground link.

#![allow(dead_code)]

enum A {
    L,
    UL,
    U,
    UR,
    R,
    DR,
    D,
    DL,
}

enum B {
    C(A, A),
}

fn main() {
    println!("{:?}", std::mem::size_of::<A>()); // prints 1
    println!("{:?}", std::mem::size_of::<B>()); // prints 2
}

1 个答案:

答案 0 :(得分:9)

两个字节对于保持借用结构成员的能力都是必需的。

Rust中的类型不是理想的值集:它具有数据布局,该布局描述了如何存储值。控制该语言的“规则”之一是将类型放入structenum内不会更改其数据布局:它在另一种类型内的布局与独立类型的布局相同,这允许你采取引用结构成员和与任何其它参考可互换地使用它们。*

在满足此约束的情况下,无法将两个A装入一个字节,因为A的大小是一个完整的字节-甚至无法寻址一个字节的一部分与repr(packed)。未使用的位只是保持未使用(除非可以通过利基填充将它们重新用于存储枚举标签)。

*好吧,repr(packed)实际上可以使这个不真实的。 Taking a reference to a packed field can cause undefined behavior,即使是安全密码!