Swift的指针分类
- 指定数据类型的类型指针:
unsafePointer<T>
和unsafeMutablePointer<T>
,T是泛型。 - 未指定类型的原生指针:
unsafeRawPointer
和unsafeMutableRawPointer
。
下表是Swift和OC指针的对比:
Swift | OC | 说明 |
---|---|---|
unsafePointer<T> | const T * | 指针及所指向的内容都不可变 |
unsafeMutablePointer <T> | * | 指针及其所指向的内存内容均可变 |
unsafeRawPointer | const void * | 指针指向未知类型 |
unsafeMutableRawPointer | void * | 指针指向未知类型 |
原生指针的简单应用:
类型指针的简单应用
注意:上面的原生指针和类型指针在偏移的时候不一样。原生指针偏移的是字节,所以要乘以8。而类型指针偏移的是步长,一个步长就是类型指针对应类型的长度,所以不需要乘以8。
OC
里面的变量指针很好获取,通过取地址符&
就可以。但是Swift
的要调用withUnsafePointer
和withUnsafeMutablePointer
获取。
class Person {
var name = "dotry"
var age = 26
}
var person = Person()
let p = withUnsafePointer(to: &person, { $0 })
类型绑定
之前探究了swift类的内存结构,现在将指针绑定到类型上。
struct Metadata {
var kind: UnsafeRawPointer
var superClass: UnsafePointer<Metadata>?
var cachedata1: UnsafeRawPointer
var cachedata2: UnsafeRawPointer
var data: UnsafeRawPointer
var flags: UInt32
var instanceAddressPoint: UInt32
var instanceSize: UInt32
var instanceAlignMask: UInt16
var reserved: UInt16
var classSize: UInt32
var classAddressPoint: UInt32
var description: UnsafeRawPointer
var iVarDestroyer: UnsafeRawPointer?
}
struct HeapObject {
var metadata: UnsafeRawPointer
var unownedRef: UInt32
var strongref: UInt32
}
class Person {
var name = "dotry"
var age = 26
}
var person = Person()
let p = withUnsafePointer(to: &person, { $0 })
// 获取实例变量的内存地址
let p1 = Unmanaged.passUnretained(person).toOpaque()
// 绑定内存,如果没有绑定则绑定到指定类型,如果已绑定择重定向到指定类型
let p2 = p1.bindMemory(to: HeapObject.self, capacity: 1)
// 绑定内存,假定内存已经绑定为某个类型
let p3 = p2.pointee.metadata.assumingMemoryBound(to: Metadata.self)
(lldb) po p3.pointee
▿ Metadata
▿ kind : 0x0000000102d9de20
- pointerValue : 4342799904
▿ superClass : Optional<UnsafePointer<Metadata>>
▿ some : 0x00000001f7c7fc70
- pointerValue : 8452045936
▿ cachedata1 : 0x00000001aa8ce9f0
- pointerValue : 7156328944
▿ cachedata2 : 0x0000003000000000
- pointerValue : 206158430208
▿ data : 0x00000002808a7902
- pointerValue : 10746493186
- flags : 2
- instanceAddressPoint : 0
- instanceSize : 40
- instanceAlignMask : 7
- reserved : 0
- classSize : 168
- classAddressPoint : 16
▿ description : 0x0000000102d975f0
- pointerValue : 4342773232
- iVarDestroyer : nil
获取结构体属性的指针
struct Student {
var name = "jack"
var age = 18
}
func printStudentAge(_ s: UnsafePointer<Student>) {
// 根据键获得内存偏移量,然后得到键的内存地址
let agePointer = UnsafeRawPointer(s) + MemoryLayout.offset(of: \Student.age)!
print(agePointer.assumingMemoryBound(to: Int.self).pointee)
}
var s = Student()
(lldb) call printStudentAge(withUnsafePointer(to: &s, { $0 }))
18
类型指针临时绑定新类型
func printANumber(_ p: UnsafePointer<Int64>) {
print(p.pointee)
}
var n = 20
// withMemoryRebound临时绑定内存
let numberPointer = withUnsafePointer(to: &n, { $0.withMemoryRebound(to: Int64.self, capacity: 1, { $0 }) })
(lldb) call printANumber(numberPointer)
20