一、介绍
Swift中的指针分为两类, typed pointer 指定数据类型指针, raw pointer 未指定数据类型的指针 (原⽣指针)
raw pointer 在 Swift 中的表示是 UnsafeRawPointer
tyepd pointer 在 Swift 中的表示是 UnsafePointer<T>
二、使用
1、原始指针:RawPionter的使用
/**
RawPionter的使用
*/
//1、分配32字节的内存空间大小
let p = UnsafeMutableRawPointer.allocate(byteCount: 32, alignment: 8)
//2、advanced代表当前 p 前进的步长,对于 RawPointer 来说,我们需要移动的是当前存储值得内存大小即,MemoryLayout.stride
//3、storeBytes: 这里就是存储我们当前的数据,这里需要制定我们当前数据的类型
for i in 0..<4{
p.advanced(by: i * 8).storeBytes(of: i + 1, as: Int.self)
}
//4、load顾明思义是加载,fromBytesOffe:是相对于我们当前 p 的首地址的偏移
for i in 0..<4{
let value = p.load(fromByteOffset: i * 8, as: Int.self)
print("index\(i),value:\(value)")
}
p.deallocate()
2、Type pointer :确定类型的指针
- 第一种
//如何获取 age 变量的地址
var age = 10
//1、通过Swift提供的简写的API,这里注意当前尾随闭包的写法
let p = withUnsafePointer(to: &age){$0}
print(p.pointee)
//2、withUnsafePointer的返回值是 unSafePointer,意味着我们不能直接修改值
var b = withUnsafePointer(to: &age){ prt in
prt.pointee += 12
}
//3、如果我们想要直接修改当前Pointer.pointee的值,那么使用withUnsafeMutablePointer
withUnsafeMutablePointer(to: &age){ptr in
ptr.pointee += 10
}
print(age)
- 第二种
//1、capacity:容量大小,当前的大小为 1 * 8字节
let ptr = UnsafeMutablePointer<Int>.allocate(capacity: 1)
//2、初始化当前的UnsafeMutablePointer<Int> 指针
ptr.initialize(to: age)
//3、下面两个成对调用,管理内存
ptr.deinitialize(count: 1)
ptr.deallocate()
3、多种方式访问类型指针
class LJTest {
var age = 18
var name = "Swift"
init() {
}
init(age: Int, name: String) {
self.age = age
self.name = name
}
}
var t = LJTest()
var t1 = LJTest(age: 100, name: "LJ")
let ptr = UnsafeMutablePointer<LJTest>.allocate(capacity: 2)
ptr.initialize(to: t)
// 注意这里的advanced 其实就是当前要移动是i * 类型大小中的i
ptr.advanced(by: 1).initialize(to: t1)
print(MemoryLayout<LJTest>.size)
print(MemoryLayout<LJTest>.stride)
print("age : \(ptr[0].age), name : \(ptr[0].name)")
print("age : \(ptr[1].age), name : \(ptr[1].name)")
print("age : \(ptr.pointee.age), name : \(ptr.pointee.name)")
print("age : \((ptr + 1).pointee.age), name : \((ptr + 1).pointee.name)")
print("age : \(ptr.successor().pointee.age), name : \(ptr.successor().pointee.name)")
ptr.deinitialize(count: 2)
ptr.deallocate()
4、绑定
- withMemoryRebound : 临时更改内存绑定类型
- bindMemory(to: Capacity:) : 更改内存绑定的类型,如果之前没有绑定,那么就是⾸次绑定;如果绑定过了,会被重新绑定为该类型。
- assumingMemoryBound: 假定内存绑定,这⾥是告诉编译器:哥们我就是这种类型,你不要检查我 了。
//练习demo,重构matedata
class LJTest {
var age = 18
var name = "Swift"
}
struct HeapObject {
var kind: UnsafeRawPointer
var strongref: UInt32
var unownedRef: UInt32
}
struct lj_swift_class {
var kind: UnsafeRawPointer
var superClass: UnsafeRawPointer
var cachedata1: UnsafeRawPointer
var cachedata2: UnsafeRawPointer
var data: UnsafeRawPointer
var flags: UInt32
var instanceAddressOffset: UInt32
var instanceSize: UInt32
var flinstanceAlignMask: UInt16
var reserved: UInt16
var classSize: UInt32
var classAddressOffset: UInt32
var description: UnsafeRawPointer
}
var t = LJTest()
let ptr = Unmanaged.passUnretained(t as AnyObject).toOpaque()
let heapObjcet = ptr.bindMemory(to: HeapObject.self, capacity: 1)
let metaPtr = heapObjcet.pointee.kind.bindMemory(to: lj_swift_class.self, capacity: 1)
print(metaPtr.pointee)
指针类型的转换
var tul = (10, "a")
func testPointer(_ p: UnsafePointer<String>){
print(p)
}
withUnsafePointer(to: &tul) { (tulPtr: UnsafePointer<(Int, String)>) in
print(tulPtr)
let rePtr = UnsafeRawPointer(tulPtr).assumingMemoryBound(to: String.self)
print(rePtr)
testPointer(rePtr)
}
//获取结构体重参数的地址
struct LJTest_Struct {
var age = 18
var name = "swift"
}
var t = LJTest_Struct()
func testPointer(_ p: UnsafePointer<String>){
let ptr = UnsafeMutableRawPointer(mutating: p)
ptr.storeBytes(of: p.pointee + "_LJ", as: String.self)
print(p)
}
withUnsafePointer(to: &t) { (ptr: UnsafePointer<LJTest_Struct>) in
print(ptr)
let rePtr = UnsafeRawPointer(ptr) + MemoryLayout<LJTest_Struct>.offset(of: \LJTest_Struct.name)!
print(rePtr)
testPointer(rePtr.assumingMemoryBound(to: String.self))
}
临时修改类型
var age = 18
let ptr = withUnsafePointer(to: &age){$0}
func testPointer(_ p: UnsafePointer<UInt64>){
print(p.pointee)
let ptr = UnsafeMutablePointer(mutating: p)
ptr.pointee += 100
print(ptr.pointee)
}
ptr.withMemoryRebound(to: UInt64.self, capacity: 1) { (p: UnsafePointer<UInt64>) in
testPointer(p)
}