【问题标题】:MemoryLayout in SwiftSwift 中的内存布局
【发布时间】:2018-08-26 01:22:51
【问题描述】:

MemoryLayout 如何计算结构的大小?

我阅读了this 的文章,我似乎理解得很好,直到我陷入了以下问题:

struct CertifiedPuppy1 {
  let age: Int
  let isTrained: Bool
  let isCertified: Bool
}

MemoryLayout<CertifiedPuppy1>.size        // 10
MemoryLayout<CertifiedPuppy1>.stride      // 16
MemoryLayout<CertifiedPuppy1>.alignment   // 8

struct CertifiedPuppy2 {
  let isTrained: Bool
  let age: Int
  let isCertified: Bool
}

MemoryLayout<CertifiedPuppy2>.size        // 17
MemoryLayout<CertifiedPuppy2>.stride      // 24
MemoryLayout<CertifiedPuppy2>.alignment   // 8


struct CertifiedPuppy3 {
  let isTrained: Bool
  let isCertified: Bool
  let age: Int
}

MemoryLayout<CertifiedPuppy3>.size        // 16 <--why not 10, like for CertifiedPuppy1 ??--
MemoryLayout<CertifiedPuppy3>.stride      // 16
MemoryLayout<CertifiedPuppy3>.alignment   // 8

问题是,为什么CertifiedPuppy3 的大小是 16,而不是像 CertifiedPuppy1 那样的 10?

【问题讨论】:

  • 每个Int 都与一个 8 字节边界对齐并且的大小为 8。
  • 啊,你的意思是CertifiedPuppy1:8 + 1 + 1 +(缓冲区6,忽略)= 10; CertifiedPuppy3:1 + 1 +(缓冲区 6,计数)+ 8 = 16

标签: swift struct swift4 memory-layout


【解决方案1】:

据我了解,几乎有一个主要规则:

  • 每个对象的起始地址必须是其对齐方式的倍数。该规则适用于所有内容 - 结构中的属性(Int、Bool 等)、结构本身以及所有其他类型。

下图显示了示例的字节布局。

让我们看看您的最后一个示例 - CertifiedPuppy3:
- isTrained (Bool) 的 alignment 为 1,这意味着它可以从任何地址开始,因此它从 0 开始。
- isCertified (Bool) 的 alignment 也是 1,所以 isCertified 从 1 开始没有问题。
- age (Int) 的 alignment 是 8,所以它只能从 0、8、16、24 开始……这就是为什么年龄的起始地址是 8 ,而不是 2。如果是 2,就会错位。

所以 CertifiedPuppy3 的大小为 16,因为它的属性必须遵循对齐规则。

与问题无关,还有这个:

  • 结构的 alignment 等于其属性的最大 alignment。

这就是 CertifiedPuppy2 的步幅为 24 的原因:CertifiedPuppy2 的对齐为 8,因为它的大小是 17,新 CertifiedPuppy2 对象的下一个可用位置是 24 - 这就是步幅 - 两个 CertifiedPuppy2 对象之间的最小距离。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-11-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-21
    • 1970-01-01
    • 2013-07-12
    相关资源
    最近更新 更多