Swift 中的内存布局

Meh*_*mar 5 struct memory-layout swift swift4

MemoryLayout 如何计算结构体的大小?

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

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
Run Code Online (Sandbox Code Playgroud)

问题是,为什么CertifiedPuppy3有大小 16 而不是 10,比如 for CertifiedPuppy1?

El *_*ble 4

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

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

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

让我们看看你的最后一个例子 - CertifiedPuppy3:
- isTrained (Bool)的对齐是 1,这意味着它可以从任何地址开始,所以它从 0 开始。 - isCertified (Bool)的对齐也是 1,所以没有问题isCertified 从 1 开始。 -年龄(Int)的对齐方式是 8,因此它只能从 0、8、16、24 开始...这就是为什么年龄的起始地址是 8,而不是 2。如果为 2 时会出现偏差。

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

与问题无关,还有这个:

  • 结构体的对齐方式等于其属性的最大对齐方式。

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

结盟