Using Structs (Bytes) with SWIFT - Struct to NSDat

2019-03-27 14:49发布

问题:

I'm trying to understand how structs work within SWIFT. I'm familiar with how .NET handles them and how it packs bytes into a structure, etc.

I'm finding some weirdness with the following code:

struct exampleStruct {
    var ModelNumber: Byte!
    var MajorVersion: Byte!
    var MinorVersion: Byte!
    var Revision: Byte!
}


var myStruct = exampleStruct (
    ModelNumber: 1,
    MajorVersion: 2,
    MinorVersion: 3,
    Revision: 4
)

myStruct.MinorVersion  // << Returns  3

// Struct to NSData.
var data = NSData(
    bytes: &myStruct,
    length: sizeof(exampleStruct)
)

println("data: \(data)")

The println returns: "data: <01000200 03000400>"

I was expecting the data to actually be: "data: <01020304>"

Any idea why SWIFT is not packing 1 byte as 1 byte, instead it's packing a byte as 2 bytes (1 byte the value and 1 byte as 00)?

On the flip side if I do the following:

var newStruct   = exampleStruct(ModelNumber: nil, MajorVersion: nil, MinorVersion: nil, Revision: nil)

var sendBytes:[Byte] = [0x1, 0x2, 0x3, 0x4]
var newData = NSData(bytes: sendBytes, length: sendBytes.count)

newData.getBytes(
    &newStruct,
    length: sizeof(exampleStruct)
)

newStruct.MinorVersion // << Returns nil

println(newData)

The println(newData) is correct and what I expect in value: <01020304>

However, when I access the minorVersion it returns nil, not what I expected as 3.

Is there a way to force the structure to respect the packing of a byte?

回答1:

Change Byte! to Byte.

Otherwise you are creating struct holding Optional<Byte> which is larger than one byte because in addition to hold a byte, it need extra byte to indicate if it is nil

Note: This may still not working as you may need something like __attribute__((packed)) to tell compiler how to deal with alignment. AFAIK, it is not available in Swift.