Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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)

like image 676
user4650218 Avatar asked Mar 09 '15 14:03

user4650218


1 Answers

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.

like image 57
Sergey Kalinichenko Avatar answered Oct 02 '22 20:10

Sergey Kalinichenko