【发布时间】:2019-12-06 15:01:12
【问题描述】:
我创建了三个几乎相同的枚举:
#[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
}
鉴于我对计算机和内存的理解,我期望它们的大小应该相同。最大的变体是大小为 16 的 [u8; 16]。因此,虽然这些枚举的第一个变体的大小确实不同,但它们的最大变体大小相同,并且变体总数相同。
我知道 Rust 可以做一些优化来确认某些类型何时存在间隙(例如,指针可能会崩溃,因为我们知道它们将无效并且为 0),但这实际上恰恰相反。我想如果我手动构建这个枚举,我可以将它放入 17 个字节中(区分只需要一个字节),所以 20 个字节和 24 个字节都让我感到困惑。
我怀疑这可能与对齐有关,但我不知道为什么,也不知道为什么有必要这样做。
谁能解释一下?
谢谢!
【问题讨论】:
-
同样值得注意的是
Arcs 也会发生这种情况(这实际上是我遇到这种行为的方式),所以虽然我知道指针和浮点数都有点特殊,但我不知道他们是如何联系起来的,这会导致这个问题。 -
更简单的例子:play.rust-lang.org/…
-
我还找到了一个很好的工具来帮助解决这个问题:
rustc带有一个print-type-sizes调试标志,可以像这样运行:cargo +nightly-2019-07-19 rustc --release -- -Z print-type-sizes(+nightly...仅在以下情况下是必需的这不是您的默认设置) -
对于后代,here 是我在上面发布的命令输出的相关部分,用于我在原始问题中发布的示例。 (我更喜欢使用不太简单的示例,因为它更容易看出某些字段如何产生影响,而另一些则没有)