小编典典

在Swift中将数据读入结构

swift

我正在尝试使用该方法来简单地读Data入Swift 4 。问题struct``withUnsafeBytes

网络UDP数据包具有以下格式:

data: 0102 0A00 0000 0B00 0000

01           : 1 byte : majorVersion      (decimal 01)
02           : 1 byte : minorVersion      (decimal 02)
0A00 0000    : 4 bytes: applicationHostId (decimal 10)
0B00 0000    : 4 bytes: versionNumber     (decimal 11)

然后我有一个扩展名Data,需要一个startlength个要读取的字节

extension Data {
    func scanValue<T>(start: Int, length: Int) -> T {
        return self.subdata(in: start..<start+length).withUnsafeBytes { $0.pointee }
    }
}

当一一读取值时,这可以正常工作:

// correctly read as decimal "1"
let majorVersion: UInt8 = data.scanValue(start: 0, length: 1)

// correctly read as decimal "2"
let minorVersion: UInt8 = data.scanValue(start: 1, length: 1)

// correctly read as decimal "10"
let applicationHostId: UInt32 = data.scanValue(start: 2, length: 4)

// correctly read as decimal "11"
let versionNumber: UInt32 = data.scanValue(start: 6, length: 4)

然后我创建了一个struct代表整个数据包的,如下所示

struct XPLBeacon {
    var majorVersion: UInt8        // 1 Byte
    var minorVersion: UInt8        // 1 Byte
    var applicationHostId: UInt32  // 4 Bytes
    var versionNumber: UInt32      // 4 Bytes
}

但是,当我直接将数据读入结构时,我遇到了一些问题:

var beacon: XPLBeacon = data.scanValue(start: 0, length: data.count)

// correctly read as decimal "1"
beacon.majorVersion

// correctly read as decimal "2"
beacon.minorVersion

// not correctly read
beacon.applicationHostId

// not correctly read
beacon.versionNumber

我应该像这样解析整个结构吗?


阅读 269

收藏
2020-07-07

共1个答案

小编典典

从数据读取整个结构不起作用,因为struct成员被 填充 到其自然边界。的内存布局struct XPLBeacon

 AB xx CCCCDDDD

哪里

 抵消成员
  0 A-majorVersion(UInt8)
  1 B-minorVersion(UInt8)
  2 xx-填充
  4 CCCC-applicationHostId(UInt32)
  8 DDDD-版本号(UInt32)

并插入填充,以便将UInt32成员对齐到其大小倍数的内存地址。这也得到了证实

print(MemoryLayout<XPLBeacon>.size) // 12

(有关Swift中对齐的更多信息,请参见 Type
Layout
)。

如果将整个数据读入结构,则按以下方式分配字节

 01 02 0A 00 00 00 0B 00 00 00
 AB xx CCCCDDDD

这就解释了为什么major/minorVersion是正确的,但applicationHostIdversionNumber
是错误的。从数据中单独读取所有成员是正确的解决方案。

2020-07-07