UnsafeMutablePointer <uint8>到[UInt8]没有内存复制

时间:2015-06-29 01:06:37

标签: swift pointers

是否可以在不复制字节的情况下从[UInt8]创建UnsafeMutablePointer<UInt8>

NSData世界中,我可以简单地致电

let data = NSData(bytesNoCopy: p, length: n, freeWhenDone: false)

然后包装指针。

2 个答案:

答案 0 :(得分:10)

正如评论中已经提到的,您可以创建一个 来自指针的UnsafeMutableBufferPointer

let a = UnsafeMutableBufferPointer(start: p, count: n)

复制数据,这意味着必须确保 只要使用a,指向的数据就有效。 不安全(可变)缓冲区指针具有类似于数组的访问方法, 如下标:

for i in 0 ..< a.count {
    print(a[i])
}

或枚举:

for elem in a {
    print(elem)
}

您可以使用

从缓冲区指针创建“真实”数组
let b = Array(a)

但这会复制数据。

这是一个完整的例子,展示了上述陈述:

func test(_ p : UnsafeMutablePointer<UInt8>, _ n : Int) {

    // Mutable buffer pointer from data:
    let a = UnsafeMutableBufferPointer(start: p, count: n)
    // Array from mutable buffer pointer
    let b = Array(a)

    // Modify the given data:
    p[2] = 17

    // Printing elements of a shows the modified data: 1, 2, 17, 4
    for elem in a {
        print(elem)
    }

    // Printing b shows the orignal (copied) data: 1, 2, 3, 4
    print(b)

}

var bytes : [UInt8] = [ 1, 2, 3, 4 ]
test(&bytes, bytes.count)

答案 1 :(得分:1)

您可以使用UnsafeBufferPointer + map来实现自己的目标。
保持头脑:指针边界应由您自己维护,而数组将由其自己完成
let bytesArray = UnsafeBufferPointer(start: bts, count: bytes.count).map{$0}
Swift 5,Xcode 11

var bytes: [UInt8] = [1, 3, 5, 7]
let count = bytes.count
print(bytes)

// MARK: - [UInt8] -> UnsafePointer<UInt8>

// producing dangling pointer warning bug?
let bts1: UnsafePointer<UInt8> = UnsafePointer(bytes)
print(bts1, bts1[0], bts1[1], bts1[2], bts1[3], bts1[4])

let bts = withUnsafePointer(to: &bytes[0]) {
    $0.withMemoryRebound(to: UInt8.self, capacity: count) { $0 }
}
print(bts, bts[0], bts[1], bts[4])

// MARK: - UnsafePointer<UInt8> -> [UInt8]
let bytesArray = UnsafeBufferPointer(start: bts, count: bytes.count).map{$0}
print(bytesArray, bytesArray[0], bytesArray[1]/*, bytesArray[4]*/)

输出:

[1, 3, 5, 7]
0x0000600001946840 1 3 5 7 0
0x0000600001946840 1 3 0
[1, 3, 5, 7] 1 3

不良样本:

/// invalid sample 1
let testA = withUnsafePointer(to: &bytes) {
    $0.withMemoryRebound(to: UInt8.self, capacity: count) { $0 }
}
print(testA, testA[0], testA[1], testA[4])

/// invalid sample 2
let testB = withUnsafePointer(to: bytes[0]) {
    $0.withMemoryRebound(to: UInt8.self, capacity: count) { $0 }
}
print(testB, testB[0], testB[1], testB[4])

输出:

0x0000000102b4f520 32 104 0
0x00007ffeed203ac0 192 58 254