Enums 当只需要一个字节时,为什么Rust使用两个字节来表示此枚举?

Enums 当只需要一个字节时,为什么Rust使用两个字节来表示此枚举?,enums,rust,memory-layout,Enums,Rust,Memory Layout,它似乎足够聪明,可以只为A使用一个字节,但不足以聪明到可以为B使用一个字节,即使只有8*8=64种可能性。有没有办法哄骗Rust解决这个问题,或者我必须手动实现更紧凑的布局 #![允许(死代码)] 列举{ L UL, U 呃,, R 博士 D DL, } 枚举B{ C(A,A),, } fn main(){ println!(“{:?}”,std::mem::size_of::());//打印1 println!(“{:?}”,std::mem::size_of::());//打印2 } 这两

它似乎足够聪明,可以只为A使用一个字节,但不足以聪明到可以为B使用一个字节,即使只有8*8=64种可能性。有没有办法哄骗Rust解决这个问题,或者我必须手动实现更紧凑的布局

#![允许(死代码)]
列举{
L
UL,
U
呃,,
R
博士
D
DL,
}
枚举B{
C(A,A),,
}
fn main(){
println!(“{:?}”,std::mem::size_of::());//打印1
println!(“{:?}”,std::mem::size_of::());//打印2
}

这两个字节都是保持借用结构成员能力所必需的

Rust中的类型不是一组理想的值:它有一个数据布局,用于描述值的存储方式。管理该语言的“规则”之一是,将类型放入
struct
enum
中不会更改其数据布局:它在另一个类型中的布局与独立类型相同,这允许您获取对结构成员的引用,并将其与任何其他引用互换使用*

在满足此约束的情况下,无法将两个
A
s放入一个字节,因为
A
的大小是一个完整的字节——即使使用
repr(packed)
,也无法寻址一个字节的一部分。未使用的位只是保持未使用状态(除非可以通过小生境填充将其重新用于存储枚举标记)


*嗯,
repr(packed)
实际上可以使这一点变得不真实,即使在安全代码中

这是因为rust的枚举是其最大变体的大小。在这种情况下,
A
是A
u8
的大小,因此在
B
中需要两个字节来容纳两个
A
s,因为没有这样的编译时微优化。无论如何,如果打包版本的使用速度比解包版本慢呢?一句话,实现的行为。@OptimisticPeach:当然,在某些平台/用例上,情况可能会更糟,但由于目前的内存延迟,通常较小的数据结构通过较少的缓存未命中来弥补解包时间。我将拥有这些对象的相当大的向量,我将半随机地访问它们,所以缓存未命中是我的用例所关心的问题。我可以选择一些我必须选择的东西,但这仍然节省了我自己手动执行打包逻辑的工作。Rust可以在一些更有限的情况下进行枚举布局优化,例如,请参见我想知道是否有可能使用某种宏来实现B的紧凑表示,这将涉及生成多个可能的表示形式,并为您实现转换,以充分利用这两个世界。。。
#![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
}