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)
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 usedata.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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With