Swift-06.指针(UnsafePointer)
2020-11-30 本文已影响0人
Fight_ing
Swift中也有专门的指针类型,这些都被定性为“Unsafe”(不安全的)。
常见的有以下4种类型:
-
UnsafePointer<Pointee>
类似于const Pointee *
-
UnsafeMutablePointer<Pointee>
类似于Pointee *
-
UnsafeRawPointer
类似于const void *
-
UnsafeMutableRawPointer
类似于void *
var age = 10
func test1(_ ptr: UnsafeMutablePointer<Int>) {
ptr.pointee += 10
}
func test2(_ ptr: UnsafePointer<Int>) {
print(ptr.pointee)
}
test1(&age)
test2(&age) // 20
print(age) // 20
var age = 10
func test3(_ ptr: UnsafeMutableRawPointer) {
ptr.storeBytes(of: 20, as: Int.self)
}
func test4(_ ptr: UnsafeRawPointer) {
print(ptr.load(as: Int.self))
}
test3(&age)
test4(&age) // 20
print(age) // 20
- 获得指向某个变量的指针:
var age = 11
var ptr1 = withUnsafeMutablePointer(to: &age) { $0 }
var ptr2 = withUnsafePointer(to: &age) { $0 }
ptr1.pointee = 22
print(ptr2.pointee) // 22
print(age) // 22
var ptr3 = withUnsafeMutablePointer(to: &age) { UnsafeMutableRawPointer($0) }
var ptr4 = withUnsafePointer(to: &age) { UnsafeRawPointer($0) }
ptr3.storeBytes(of: 33, as: Int.self)
print(ptr4.load(as: Int.self)) // 33
print(age) // 33
- 获得指向堆空间实例的指针:
// UnsafeRawPointer(bitPattern:)函数用来生成指向某一地址的指针
var ptr = UnsafeRawPointer(bitPattern: 0x100001234)
class Person {}
// 类似于 *p = person
var person = Person()
// p = &person, p是person变量的地址值
var ptr = withUnsafePointer(to: &person) { UnsafeRawPointer($0) }
// ptr.load(as: UInt.self) 类似于 *p, 取出地址中存储的值,也就是Person实例在堆上的地址值
var heapPtr = UnsafeRawPointer(bitPattern: ptr.load(as: UInt.self))
print(heapPtr!)
- 创建指针:
- 非泛型
// 创建 var ptr = malloc(16) // 存 ptr?.storeBytes(of: 11, as: Int.self) ptr?.storeBytes(of: 22, toByteOffset: 8, as: Int.self) // 取 print((ptr?.load(as: Int.self))!) // 11 // fromByteOffset: 地址偏移 print((ptr?.load(fromByteOffset: 8, as: Int.self))!) // 22 // 销毁 free(ptr) var ptr = UnsafeMutableRawPointer.allocate(byteCount: 16, alignment: 1) ptr.storeBytes(of: 11, as: Int.self) // advanced: 也是地址偏移 ptr.advanced(by: 8).storeBytes(of: 22, as: Int.self) print(ptr.load(as: Int.self)) // 11 print(ptr.advanced(by: 8).load(as: Int.self)) // 22 // 销毁 ptr.deallocate()
- 泛型
基础数据类型:
对象类型:var ptr = UnsafeMutablePointer<Int>.allocate(capacity: 3) ptr.initialize(to: 11) // successor()后继, 表示向后走<Int>长度个字节 ptr.successor().initialize(to: 22) ptr.successor().successor().initialize(to: 33) print(ptr.pointee) // 11 // 这里的 + 指的是指针的加,步长为<Int>长度个字节 print((ptr + 1).pointee) // 22 print((ptr + 2).pointee) // 33 print(ptr[0]) // 11 print(ptr[1]) // 22 print(ptr[2]) // 33 ptr.deinitialize(count: 3) ptr.deallocate()
class Person { var age: Int var name: String init(age: Int, name: String) { self.age = age self.name = name } deinit { print(name, "deinit") } } var ptr = UnsafeMutablePointer<Person>.allocate(capacity: 3) ptr.initialize(to: Person(age: 10, name: "Jack")) (ptr + 1).initialize(to: Person(age: 11, name: "Rose")) (ptr + 2).initialize(to: Person(age: 12, name: "Kate")) // Jack deinit // Rose deinit // Kate deinit ptr.deinitialize(count: 3) ptr.deallocate()
- 指针之间的转换
var ptr = UnsafeMutableRawPointer.allocate(byteCount: 16, alignment: 1) ptr.assumingMemoryBound(to: Int.self).pointee = 11 (ptr + 8).assumingMemoryBound(to: Double.self).pointee = 22.0 // 只改变类型,而不改变其值 //(值指的是二进制数据,也就是你告诉计算机这是什么类型,计算机就按什么类型解读这些二进制数据) print(unsafeBitCast(ptr, to: UnsafePointer<Int>.self).pointee) // 11 print(unsafeBitCast(ptr + 8, to: UnsafePointer<Double>.self).pointee) // 22.0 ptr.deallocate() // unsafeBitCast是忽略数据类型的强制转换,不会因为数据类型的变化而改变原来的内存数据 // 类似于C++中的reinterpret_cast class Person {} var person = Person() var ptr = unsafeBitCast(person, to: UnsafeRawPointer.self) print(ptr)
- 关于指针的强制类型转换可参考这篇