1

Why does a variable UInt8 in a swift struct show an offset of 2? However a struct of just UInt8s shows an offset of 1?

struct Test {
    let a: UInt8
    let b: UInt16
}

MemoryLayout<Test>.offset(of: \Test.a) // 0
MemoryLayout<Test>.offset(of: \Test.b) // 2 (not 1)

struct Test2 {
    let a: UInt8
    let b: UInt8
    let c: UInt8
}

MemoryLayout<Test2>.offset(of: \Test2.a) // 0
MemoryLayout<Test2>.offset(of: \Test2.b) // 1
MemoryLayout<Test2>.offset(of: \Test2.c) // 2
Michael Ozeryansky
  • 7,204
  • 4
  • 49
  • 61
  • 2
    `b` is an `UInt16` and that is aligned to an even address. Details at https://github.com/apple/swift/blob/master/docs/ABI/TypeLayout.rst – Martin R Oct 04 '18 at 04:36

1 Answers1

1

This has to do with how Swift aligns your properties in memory. For your first struct, the alignment is 2, whereas your second struct has an alignment of 1.

Your properties in Test are not stored in memory all packed together like this:

x y y

where x represents a byte for a, and y represents a byte for b.

It looks more like this:

x   y y

Notice the padding after x.

The point I am trying to make here is that Swift divides up a part of memory into "slices" to put the properties of your structs in. These equal slices has to be able to contain all your properties. This is why in Test, the memory has to be cut up into slices of 2 bytes, to fit in a UInt16.

In Test2 however, cutting up the memory into slices of 1 byte is enough to contain UInt8s.

This "How many bytes per slice" number is the alignment.

For why Swift cuts memory up this way, read this.

Sweeper
  • 213,210
  • 22
  • 193
  • 313