004-Swift进阶-指针-metadata结构

2020-12-17  本文已影响0人  Stronger_J

一、介绍

Swift中的指针分为两类, typed pointer 指定数据类型指针, raw pointer 未指定数据类型的指针 (原⽣指针)
raw pointer 在 Swift 中的表示是 UnsafeRawPointer
tyepd pointer 在 Swift 中的表示是 UnsafePointer<T>


image.png

二、使用

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、绑定

//练习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)
}
上一篇 下一篇

猜你喜欢

热点阅读