Michael Ozeryansky
Michael Ozeryansky

Reputation: 8053

Swift offset(of:) for UInt8 has 2 byte offset

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

Upvotes: 1

Views: 361

Answers (1)

Sweeper
Sweeper

Reputation: 272760

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.

Upvotes: 1

Related Questions