Size of struct with optionals in swift

Viewed 314

Strange result of call MemoryLayout<SampleStruct>.size. it returns 41 on the following struct.

struct SampleStruct {
    var tt: Int?
    var qq: Int?
    var ww: Int?
}

That not divisible by 3! Meantime size of Int? is 9. How it can be?

1 Answers

Int? aka Optional<Int> is an enum type and requires 9 bytes: 8 bytes for the integer (if we are on a 64-bit platform) plus one byte for the case discriminator.

In addition, each integer is aligned in memory to its natural (8 byte) boundary, by inserting padding bytes.

So your struct would look like this in memory:

i1 i1 i1 i1 i1 i1 i1 i1      // 8 bytes for the first integer
c1 p1 p1 p1 p1 p1 p1 p1      // 1 byte for the first case discriminator,
                             // ... and 7 padding bytes
i2 i2 i2 i2 i2 i2 i2 i2      // 8 bytes for the second integer
c2 p2 p2 p2 p2 p2 p2 p2      // 1 byte for the second case discriminator
                             // ... and 7 padding bytes
i3 i3 i3 i3 i3 i3 i3 i3      // 8 bytes for the third integer
c3                           // 1 byte for the third case discriminator

That makes a total of 41 bytes.

If SampleStruct values are stored contiguously in an array then additional padding is inserted between the elements to ensure that each value starts on a 8-byte boundary. This additional padding is taken into account by the stride:

print(MemoryLayout<SampleStruct>.size)    // 41
print(MemoryLayout<SampleStruct>.stride)  // 48

You can find the gory details in the Type Layout document of the Swift documentation.

Related