user4650218
user4650218

Reputation: 73

Swift calculates wrong size of struct

Today I encountered a problem with Swift structs. See the following struct for example:

struct TestStruct {
    var test: UInt16
    var test2: UInt32
}

I would assume that the size of this struct in total is 6 bytes, because UInt16 is 2 bytes and UInt32 is 4 bytes large.

The following code prints 6 (which is correct):

println(sizeof(UInt32) + sizeof(UInt16))

But if I check the size of the struct with

println(sizeof(TestStruct))

it prints 8 and not 6.

If I try the same with the following struct:

struct TestStruct2 {
    var test: UInt16
    var test2: UInt16
    var test3: UInt16
}

Then

println(sizeof(TestStruct2))

prints the correct value: 6. But the size of TestStruct should be the same as the size of TestStruct2.

Why is the first struct 8 bytes large? Am I doing something wrong or is this a bug?

(tested with Xcode 6.1.1 (6A2008a) on OS X Mavericks, normal command line application for Mac)

Upvotes: 7

Views: 4980

Answers (1)

Sergey Kalinichenko
Sergey Kalinichenko

Reputation: 726569

This is because Swift aligns UInt32 field at a 4-byte boundary by inserting a two-byte "gap" between UInt16 and UInt32. If you switch the fields so that the 32-bit field comes first, the gap would be eliminated:

struct TestStruct1 {
    var test: UInt16
    var test2: UInt32
}
println(sizeof(TestStruct1)) // <<== Prints 8

struct TestStruct2 {
    var test2: UInt32
    var test: UInt16
}
println(sizeof(TestStruct2)) // <<== Prints 6

You can also place another UInt16 into that gap without changing the size of your structure:

struct TestStruct3 {
    var test0: UInt16
    var test1: UInt16
    var test2: UInt32
}
println(sizeof(TestStruct3)) // <<== Prints 8

But then, how can I get data from NSData into this aligned struct? If I use data.getBytes(&aStruct, length: sizeof(AStruct)) then I have wrong values.

Not necessarily: if you saved AStruct using the same method, then the gaps would be there in NSData as well, so obtaining your binary data would be like placing "a cookie cutter" onto pre-filled array of bytes with the same alignment.

Upvotes: 8

Related Questions