目录
Swift指针Unsafe Pointer
如果不是只读,可以修改 ( 写入 ),就加一个 Mutable,
如果没有具体的类型( 通过泛型的方式 ),就加一个 Raw,
如果不是一个单独的对象 ( 指向集合类型 ),就加上 buffer.
Unsafe [ Mutable ] [ Raw ] [ Buffer ] Pointer [ ]
苹果没有编译保护的 [ 可变的 ] [没有类型的] [ 是集合的 ] 指针 [< 具体的类型 >]
对照Objective-C
- swift 的
unsafeMutablePointer<T>
: OC 的 T * - swift 的
unsafePointer<T>
: OC 的 const T * - swift 的 unsafeRawPointer: OC 的 const void *
- swift 的 unsafeMutableRawPointer: OC 的 void *
例子
例子 1, 无类型的指针
let count = 2 let stride = MemoryLayout<Int>.stride let alignment = MemoryLayout<Int>.alignment let byteCount = stride * count do { print("Raw pointers") let pointer = UnsafeMutableRawPointer.allocate( byteCount: byteCount, alignment: alignment) // 指针的创建,与销毁 defer { // 需要手动管理,指针的内存 pointer.deallocate() } // store 存值 pointer.storeBytes(of: 42, as: Int.self) // 指针需要移动 stride,才能到达下一个指针 pointer.advanced(by: stride).storeBytes(of: 6, as: Int.self) // (pointer+stride).storeBytes(of: 6, as: Int.self), 这个是另一种方式 // load 取值 print(pointer.load(as: Int.self)) print(pointer.advanced(by: stride).load(as: Int.self)) // 集合的指针 let bufferPointer = UnsafeRawBufferPointer(start: pointer, count: byteCount) for (index, byte) in bufferPointer.enumerated() { print("byte \(index): \(byte)") } }
2, 具体类型的指针
具体类型的指针,可以通过指针的 pointee
属性,方便的操作 load 和 store
let count = 2 let stride = MemoryLayout<Int>.stride let alignment = MemoryLayout<Int>.alignment let byteCount = stride * count do { print("Typed pointers") let pointer = UnsafeMutablePointer<Int>.allocate(capacity: count) pointer.initialize(repeating: 0, count: count) // 与上面的一样,指针的内存,需要手动管理 defer { pointer.deinitialize(count: count) pointer.deallocate() } pointer.pointee = 42 // 因为编译器做了优化,指针到达下一个指针,不需要移动 stride // 指针移动 1 ,就到了下一个指针 pointer.advanced(by: 1).pointee = 6 print( pointer.pointee ) print(pointer.advanced(by: 1).pointee) let bufferPointer = UnsafeBufferPointer(start: pointer, count: count) for (index, value) in bufferPointer.enumerated() { print("value \(index): \(value)") } }
例子 3: 通过绑定内存,来做指针的转化
bindMemory
let count = 2 let stride = MemoryLayout<Int>.stride let alignment = MemoryLayout<Int>.alignment let byteCount = stride * count do { print("Converting raw pointers to typed pointers") let rawPointer = UnsafeMutableRawPointer.allocate( byteCount: byteCount, alignment: alignment) defer { rawPointer.deallocate() } // 这一步,将任意指针,转化为类型指针 let typedPointer = rawPointer.bindMemory(to: Int.self, capacity: count) typedPointer.initialize(repeating: 0, count: count) defer { typedPointer.deinitialize(count: count) } typedPointer.pointee = 42 typedPointer.advanced(by: 1).pointee = 6 // 看结果 print(typedPointer.pointee) print(typedPointer.advanced(by: 1).pointee) let bufferPointer = UnsafeBufferPointer(start: typedPointer, count: count) for (index, value) in bufferPointer.enumerated() { print("value \(index): \(value)") } }
例子 4, 查看指针的字节
struct Demo{ let number: UInt32 let flag: Bool } do { print("Getting the bytes of an instance") var one = Demo(number: 25, flag: true) withUnsafeBytes(of: &one) { bytes in for byte in bytes { print(byte) } } }
例子 4.1, 指针的字节, 算 check sum
struct Demo{ let number: UInt32 let flag: Bool } do { print("Checksum the bytes of a struct") var one = Demo(number: 25, flag: true) let checksum = withUnsafeBytes(of: &one) { (bytes) -> UInt32 in return ~bytes.reduce(UInt32(0)) { $0 + numericCast($1) } } print("checksum", checksum) // checksum 4294967269 }
checeSum 的使用,分为 checeSum 的计算与校验
本文简单描述 checeSum 的计算
数据块,分为 n 个包, size 相同
拿包的字节,计算 checkSum, checkSum 的大小限制在包的 size
例子 5, 获取变量的指针
var cat = "fly" // 返回的是,闭包中的参数 // withUnsafePointer , 把闭包里面的结果,rethrow 出去 ( 相当于 return 出来 ) let warrior = withUnsafePointer(to: &cat, { $0 }) print(warrior.pointee)
例子 6, 指向多个元素的指针
struct Cat{ var habit = "eat" var paws = 6 var name = "load" } let ptr = UnsafeMutablePointer<Cat>.allocate(capacity: 2) // 指向两个 Cat 结构体 ptr.initialize(repeating: Cat(), count: 2) defer{ ptr.deinitialize(count: 2) ptr.deallocate() } var one = Cat() one.paws = 8 ptr[1] = one // 以下两个等价 print(ptr[0]) print(ptr.pointee) // 下面 3 个等价 print(ptr[1]) print((ptr + 1).pointee) print(ptr.successor().pointee)
例子 7: 元素组合的探索
var pair = (66, 666) func test(ptr: UnsafePointer<Int>){ print(ptr.pointee) print(ptr.successor().pointee) } withUnsafePointer(to: &pair) { (tuplePtr: UnsafePointer<(Int, Int)>) in // 假定内存绑定,不需要经过内存检查 test(ptr: UnsafeRawPointer(tuplePtr).assumingMemoryBound(to:Int.self)) }
参考了 Unsafe Swift: Using Pointers and Interacting With C