我正在尝试使用Data
方法将裸struct
读入Swift 4 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
进行了扩展,该扩展需要一个start
和字节的length
来读取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
我应该像这样解析整个结构吗?
最佳答案
从数据读取整个结构不起作用,因为
结构成员被填充到其自然边界。这struct XPLBeacon
的内存布局为
A B x x C C C C D D D D
where
offset member 0 A - majorVersion (UInt8) 1 B - minorVersion (UInt8) 2 x x - padding 4 C C C C - applicationHostId (UInt32) 8 D D D D - versionNumber (UInt32)
and the padding is inserted so that the UInt32
members arealigned to memory addresses which are a multiple of their size. This isalso confirmed by
print(MemoryLayout<XPLBeacon>.size) // 12
(有关Swift中对齐的更多信息,请参见
Type Layout)。
如果您将整个数据读入结构,则将分配字节
如下
01 02 0A 00 00 00 0B 00 00 00
A B x x C C C C D D D D
这就解释了为什么
major/minorVersion
是正确的,但是applicationHostId
和versionNumber
错了。将所有成员与数据分开读取是正确的解决方案。关于swift - 在Swift中将数据读入结构,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/47525922/