Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/19.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Swift 如何创建一个;“对齐”;字节数组并从中读取?_Swift_Pointers_Memory - Fatal编程技术网

Swift 如何创建一个;“对齐”;字节数组并从中读取?

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

我希望能够使用该方法从[UInt8]数组中读取大量字节,并在每次读取时将其对应的类型作为
无符号整数
固定宽度整数

在接下来的两种方法中,都会引发“致命错误:从未对齐的原始指针加载”异常,因为
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)