我创建了三个几乎相同的枚举:
#[derive(Clone, Debug)]
pub enum Smoller {
Int(u8),
Four([u8; 4]),
Eight([u8; 8]),
Twelve([u8; 12]),
Sixteen([u8; 16]),
}
#[derive(Clone, Debug)]
pub enum Smol {
Float(f32),
Four([u8; 4]),
Eight([u8; 8]),
Twelve([u8; 12]),
Sixteen([u8; 16]),
}
#[derive(Clone, Debug)]
pub enum Big {
Float(f64),
Four([u8; 4]),
Eight([u8; 8]),
Twelve([u8; 12]),
Sixteen([u8; 16]),
}
pub fn main() {
println!("Smoller: {}", std::mem::size_of::<Smoller>()); // => Smoller: 17
println!("Smol: {}", std::mem::size_of::<Smol>()); // => Smol: 20
println!("Big: {}", std::mem::size_of::<Big>()); // => Big: 24
}
Run Code Online (Sandbox Code Playgroud)
鉴于对计算机和内存的了解,我期望它们的大小应相同。最大的变体是[u8; 16]大小为16的。因此,尽管这些枚举的第一个变体的大小确实有所不同,但它们具有的最大变体的大小相同,并且变体总数相同。
我知道Rust可以做一些优化来确认某些类型何时存在间隙(例如,指针会折叠,因为我们知道它们将无效且为0),但这确实是相反的。我认为,如果我是手工构造此枚举,我可以将其装入17个字节(辨别只需要一个字节),因此20个字节和24个字节都让我感到困惑。
我怀疑这可能与对齐有关,但是我不知道为什么,也不知道为什么有必要。
有人可以解释吗?
谢谢!
大小必须至少为17个字节,因为它的最大变体为16个字节,并且需要一个额外的字节来进行判别(在某些情况下,编译器可以很聪明,将判别式放入变体的未使用位中,但是无法在这里执行此操作)。
同样,的大小Big必须为8字节的倍数才能正确对齐 f64。大于17的8的较小倍数是24。类似地,Smol不能仅是17个字节,因为它的大小必须是4个字节(的大小f32)的倍数。Smoller仅包含,u8因此可以对齐到1个字节。
| 归档时间: |
|
| 查看次数: |
87 次 |
| 最近记录: |