美文网首页
004-Swift进阶-指针-metadata结构

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

作者: Stronger_J | 来源:发表于2020-12-17 10:58 被阅读0次

一、介绍

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

  • 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)
}

相关文章

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

    一、介绍 Swift中的指针分为两类, typed pointer 指定数据类型指针, raw pointer 未...

  • C语言20 结构体指针

    C语言20 结构体指针 探测结构体指针的特性 ++、-- 加法与减法 指针相减 使用结构体指针 结构体指针一定要指...

  • 12 C指针

    1、指针定义 2、指针进阶 3、指针使用 4、多级指针 4、指针和数组 5、指针和字符串 6、高级指针之和指向函数的指针

  • 14.5 结构和其他数据形式:指针和结构

    【结构声明】 声明结构指针 关键字struct、结构标记guy、指针标志 * 、其后是指针名。 如果barney是...

  • C语言-5、结构体

    写法一 写法二 写法三 结构体指针 结构体指针 与 动态内存开辟 结构体的数组 结构体与结构体指针 取别名 取别名...

  • 函数指针,联合体,枚举,结构体和结构体指针

    函数指针 联合体 枚举 别名 结构体 结构体指针

  • Go语言之结构体指针

    结构体本身属于值类型,可以通过指针操作结构体,编程引用类型的数据,通过new()创建指针 结构体指针

  • 深入理解C指针

    标签(空格分隔): C语言进阶 本文将会持续更新。。。。 指向指针的指针 在c语言中指针的操作时通过指针变量来实现...

  • Objective-C底层数据结构

    Objective-C底层数据结构 类的数据结构 Class(指针) Method(指针) Ivar(指针) Ca...

  • 4.Fabric账本与World State

    Fabric 账本 Fabric 区块链 Fabric 区块结构 Block Metadata(写入时间,写入人,...

网友评论

      本文标题:004-Swift进阶-指针-metadata结构

      本文链接:https://www.haomeiwen.com/subject/buoogktx.html