Swift 如何创建一个;“对齐”;字节数组并从中读取?
我希望能够使用该方法从[UInt8]数组中读取大量字节,并在每次读取时将其对应的类型作为Swift 如何创建一个;“对齐”;字节数组并从中读取?,swift,pointers,memory,Swift,Pointers,Memory,我希望能够使用该方法从[UInt8]数组中读取大量字节,并在每次读取时将其对应的类型作为无符号整数,固定宽度整数 在接下来的两种方法中,都会引发“致命错误:从未对齐的原始指针加载”异常,因为load 我已尝试使用连续数组 var words: ContiguousArray<UInt8> = [0x01, 0x00, 0x03, 0x0a, 0x00, 0x01, 0x00, 0xec, 0xfa, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x
无符号整数
,固定宽度整数
在接下来的两种方法中,都会引发“致命错误:从未对齐的原始指针加载”异常,因为load
我已尝试使用连续数组
var words: ContiguousArray<UInt8> = [0x01, 0x00, 0x03, 0x0a, 0x00, 0x01, 0x00, 0xec, 0xfa, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x20, 0x00, 0x00, 0xe0, 0x88, 0x47, 0xa3, 0xd6, 0x6b, 0xd6, 0x01, 0x4c, 0xff, 0x08]
var offset = 0
let byte = words.withUnsafeBytes { $0.load(fromByteOffset: offset, as: UInt8.self) }
offset += MemoryLayout<UInt8>.size
let bytes = words.withUnsafeBytes { $0.load(fromByteOffset: offset, as: UInt16.self) }
XCTAssertEqual(byte, UInt8(littleEndian: 0x01))
XCTAssertEqual(bytes, UInt16(littleEndian: 0x0003))
var字:连续数组=[0x01,0x00,0x03,0x0a,0x00,0x01,0x00,0xec,0xfa,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7c,0x20,0x00,0x00,0x00,0xe0,0x88,0x47,0xa3,0xd6,0xd6,0x01,0x4c,0xff,0x08]
var偏移量=0
让byte=words.withUnsafeBytes{$0.load(fromByteOffset:offset,as:UInt8.self)}
偏移量+=MemoryLayout.size
let bytes=words.withUnsafeBytes{$0.load(fromByteOffset:offset,as:UInt16.self)}
xctasertequal(字节,UInt8(littleEndian:0x01))
xctasertequal(字节,UInt16(littleEndian:0x0003))
分配和初始化
var words:[UInt8]=[0x01、0x00、0x03、0x0a、0x00、0x01、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x7c、0x20、0x00、0x00、0x00、0xe0、0x88、0x47、0xa3、0xd6、0xd6、0x01、0x4c、0xff、0x08]
let uint8Pointer=unsafemeutablepointer.allocate(容量:words.count)
UINT8指针.initialize(从:&words,计数:words.count)
设rawPointer=unsafemeutablerawpointer(uint8Pointer)
var偏移量=0
让byte=UInt8(bigEndian:rawPointer.load(fromByteOffset:offset,as:UInt8.self))
偏移量+=MemoryLayout.size
让bytes=UInt16(bigEndian:rawPointer.load(fromByteOffset:offset,as:UInt16.self))
rawPointer.deallocate()
UINT8指针。取消初始化(计数:单词数。计数)
uint8Pointer.deallocate()
xctasertequal(字节,UInt8(littleEndian:0x01))
xctasertequal(字节,UInt16(littleEndian:0x0003))
你能指出我的误解在哪里,并提供一个有效的例子吗?有多个问题:
unsafemeutablepointer
不保证对齐。可以使用POSIX函数(比如POSIX_memalign
),但如果
a:UInt16
,b:UInt8
,c:UInt32
已打包(按此顺序)
那么就没有办法对齐该缓冲区,从而使所有整数值都正确对齐
数组
、连续数组
或数据
作为字节源并不重要
let byteArray: Array<UInt8> = [0x01, 0x00, 0x03, 0x0a]
var offset = 0
let ui8 = byteArray[offset]
print(ui8) // 1
offset += MemoryLayout<UInt8>.size
let ui16 = UInt16(byteArray[offset]) << 8 + UInt16(byteArray[offset + 1])
print(ui16) // 3
let byteArray:Array=[0x01,0x00,0x03,0x0a]
var偏移量=0
设ui8=byteArray[offset]
打印(ui8)//1
偏移量+=MemoryLayout.size
设ui16=UInt16(byteArray[offset])保证字节数组“对齐”的一种方法是使用相同的无符号整数
,固定宽度整数
类型。由于数组是同质的,因此每种类型的大小都可以保证对齐
e、 g.保存字节类型的[UInt8]数组
var array: [UInt8] = [0x01, 0x00, 0x03]
var offset = 0
let byte = array.withUnsafeBytes { $0.load(fromByteOffset: offset, as: UInt8.self) }
offset += MemoryLayout<UInt8>.size
let bytee = array.withUnsafeBytes { $0.load(fromByteOffset: offset, as: UInt8.self) }
offset += MemoryLayout<UInt8>.size
let byteee = array.withUnsafeBytes { $0.load(fromByteOffset: offset, as: UInt8.self) }
XCTAssertEqual(byte, 0x01)
XCTAssertEqual(bytee, 0x00)
XCTAssertEqual(byteee, 0x03)
var array: [UInt8] = [0x01, 0x00, 0x03, 0x0a, 0x00, 0x01]
var offset = 0
let bytes = UInt16(bigEndian: array.withUnsafeBytes { $0.load(fromByteOffset: offset, as: UInt16.self) })
offset += MemoryLayout<UInt16>.size
let bytess = UInt16(bigEndian: array.withUnsafeBytes { $0.load(fromByteOffset: offset, as: UInt16.self) })
offset += MemoryLayout<UInt16>.size
let bytesss = UInt16(bigEndian: array.withUnsafeBytes { $0.load(fromByteOffset: offset, as: UInt16.self) })
XCTAssertEqual(bytes, 0x0100)
XCTAssertEqual(bytess, 0x030a)
XCTAssertEqual(bytesss, 0x0001)
var数组:[UInt8]=[0x01、0x00、0x03]
var偏移量=0
让byte=array.withUnsafeBytes{$0.load(fromByteOffset:offset,as:UInt8.self)}
偏移量+=MemoryLayout.size
让bytee=array.withUnsafeBytes{$0.load(fromByteOffset:offset,as:UInt8.self)}
偏移量+=MemoryLayout.size
让byteee=array.withUnsafeBytes{$0.load(fromByteOffset:offset,as:UInt8.self)}
xctasertequal(字节,0x01)
XCTASERTEQUAL(bytee,0x00)
xctasertequal(byteee,0x03)
e、 g.一个[UInt8]数组,包含2个字节类型
var array: [UInt8] = [0x01, 0x00, 0x03]
var offset = 0
let byte = array.withUnsafeBytes { $0.load(fromByteOffset: offset, as: UInt8.self) }
offset += MemoryLayout<UInt8>.size
let bytee = array.withUnsafeBytes { $0.load(fromByteOffset: offset, as: UInt8.self) }
offset += MemoryLayout<UInt8>.size
let byteee = array.withUnsafeBytes { $0.load(fromByteOffset: offset, as: UInt8.self) }
XCTAssertEqual(byte, 0x01)
XCTAssertEqual(bytee, 0x00)
XCTAssertEqual(byteee, 0x03)
var array: [UInt8] = [0x01, 0x00, 0x03, 0x0a, 0x00, 0x01]
var offset = 0
let bytes = UInt16(bigEndian: array.withUnsafeBytes { $0.load(fromByteOffset: offset, as: UInt16.self) })
offset += MemoryLayout<UInt16>.size
let bytess = UInt16(bigEndian: array.withUnsafeBytes { $0.load(fromByteOffset: offset, as: UInt16.self) })
offset += MemoryLayout<UInt16>.size
let bytesss = UInt16(bigEndian: array.withUnsafeBytes { $0.load(fromByteOffset: offset, as: UInt16.self) })
XCTAssertEqual(bytes, 0x0100)
XCTAssertEqual(bytess, 0x030a)
XCTAssertEqual(bytesss, 0x0001)
var数组:[UInt8]=[0x01、0x00、0x03、0x0a、0x00、0x01]
var偏移量=0
let bytes=UInt16(bigEndian:array.withUnsafeBytes{$0.load(fromByteOffset:offset,as:UInt16.self)})
偏移量+=MemoryLayout.size
让bytess=UInt16(bigEndian:array.withUnsafeBytes{$0.load(fromByteOffset:offset,as:UInt16.self)})
偏移量+=MemoryLayout.size
让bytesss=UInt16(bigEndian:array.withUnsafeBytes{$0.load(fromByteOffset:offset,as:UInt16.self)})
xctasertequal(字节,0x0100)
XCTAssertEqual(bytess,0x030a)
xctasertequal(bytesss,0x0001)
误解在于,当数组中存储的类型由于大小不匹配而无法对齐时,就不可能有“对齐”的字节数组
在本例中,UInt8的大小为1字节,UInt16的大小为2字节。创建未对齐的数组时,UnsafeRawBufferPointer.load(fromByteOffset:as:)不支持该数组。
我不确定是否理解答案。你是说没有办法创建一个原始字节缓冲区,它有一个对齐的内存,这样指针就可以读取它了吗?不是说:“unsafemeutablepointer不提供自动内存管理或对齐保证。”。Swift中提供POSIX函数(如POSIX_memalign
)。但是,如果这些值位于缓冲区中的任意位置(如示例中偏移量1处的UInt16),则这没有帮助。请将其作为答案发布,以便我可以接受?考虑到无法满足UnsafeRawBufferPointer.load(fromByteOffset:as:)
的前提条件,当使用偏移量时,使用Swift时是否存在任何用例?@qnoid:我已将其添加到答案中。是的,load(fromByteOffset:as:)
方法是
var array: [UInt8] = [0x01, 0x00, 0x03, 0x0a, 0x00, 0x01]
var offset = 0
let bytes = UInt16(bigEndian: array.withUnsafeBytes { $0.load(fromByteOffset: offset, as: UInt16.self) })
offset += MemoryLayout<UInt16>.size
let bytess = UInt16(bigEndian: array.withUnsafeBytes { $0.load(fromByteOffset: offset, as: UInt16.self) })
offset += MemoryLayout<UInt16>.size
let bytesss = UInt16(bigEndian: array.withUnsafeBytes { $0.load(fromByteOffset: offset, as: UInt16.self) })
XCTAssertEqual(bytes, 0x0100)
XCTAssertEqual(bytess, 0x030a)
XCTAssertEqual(bytesss, 0x0001)