美文网首页
Swift中指针

Swift中指针

作者: Sweet丶 | 来源:发表于2022-11-29 23:37 被阅读0次

    Swift中有4个指针类型:UnsafePointerUnsafeMutablePointerUnsafeRawPointerUnsafeMutableRawPointer,通过指针可以直接修改指向的内存数据,下面简单介绍下它们的几个常见用法。

    一、从已有的变量获取指针
    1. 获取指向变量或者指向对象的指针、读写指向变量的值的方式如下:
    var age = 10
    
    // 通过withUnsafeXXXXPointer创建指向变量或对象的指针
    func testGetPointer() {
        // 1.指向值类型变量时
        var ptr1 = withUnsafePointer(to: &age, { $0 })
        var ptr2 = withUnsafeMutablePointer(to: &age, { $0 })
    //    ptr1.pointee = 15 // ptr1不可变,这里报错
        ptr2.pointee = 20
        print("ptr1=\(ptr1.pointee), ptr2=\(ptr2.pointee)") // 都是20
        // 使用原始指针
        var ptr3 = withUnsafePointer(to: &age, { UnsafeRawPointer($0) })
        var ptr4 = withUnsafeMutablePointer(to: &age, { UnsafeMutableRawPointer($0) })
        ptr4.storeBytes(of: 50, as: Int.self)
        print("ptr3=\(ptr3.load(as: Int.self)), ptr4=\(ptr4.load(as: Int.self))") // 都是50
        
        // 2.指向对象时
        var hba = HBA(no: "no119", name: "name120")
        let ptr5 = withUnsafePointer(to: &hba, { $0 })
        let ptr6 = withUnsafeMutablePointer(to: &hba, { $0 })
        ptr6.pointee.no = "no911"
        print("no=\(ptr5.pointee.no),name=\(ptr5.pointee.name)") // no=no911,name=name120
        
        // 原始指针
        var ptr7 = withUnsafePointer(to: &hba, { UnsafeRawPointer($0) })
    //    var ptr8 = withUnsafeMutablePointer(to: &hba, { UnsafeMutableRawPointer($0) })
        // ptr7、ptr8的值是hba指针的地址值,要访问到hba对象的堆空间地址值还需要如下操作
        // 根据bitPattern参数(堆空间地址)初始化一个指针
        var heapPtr = UnsafeRawPointer(bitPattern: ptr7.load(as: UInt.self))!
        // 将这个堆空间指针转换类型后就可以很方便得访问属性
        let hba2 = unsafeBitCast(heapPtr, to: HBA.self)
        print("hba2==", hba2.name)
    }
    
    1. 作为函数参数时,可变类型的指针UnsafeMutablePointerUnsafeRawPointer与inout参数效果类似,都可以修改指向的值,不同之处在于inout参数可以直接改。
    func testPointer()  {
        useinout(&age)
        usePointer1(&age)
        usePointer2(&age)
        usePointer3(&age)
        usePointer4(&age)
    }
    
    func useinout(_ ptr: inout Int) {
        print("inout-ptr前:\(ptr)")
        ptr = 90
        print("inout-ptr后:\(ptr)")
    }
    
    // UnsafePointer不可修改指向内存
    func usePointer1(_ ptr: UnsafePointer<Int>) { // 相当于const int *
        print("ptr.pointee:\(ptr.pointee)")
    }
    
    // UnsafeMutablePointer可修改指向内容
    func usePointer2(_ ptr: UnsafeMutablePointer<Int>) {// 相当于int *
        print("ptr.pointee前\(ptr.pointee)")
        ptr.pointee = 20
        print("ptr.pointee后\(ptr.pointee)")
    }
    
    // 不可修改的原始指针
    func usePointer3(_ rawptr: UnsafeRawPointer) { // 相当于const void *
        print("rawptr:\(rawptr.load(as: Int.self))")
    }
    
    // UnsafeMutableRawPointer可修改指向内容的原始指针
    func usePointer4(_ rawptr: UnsafeMutableRawPointer) {// 相当于void *
        print("rawptr.pointee前\(rawptr.load(as: Int.self))")
        rawptr.storeBytes(of: 19, as: Int.self)
        print("rawptr.pointee后\(rawptr.load(as: Int.self))") // 19
    }
    
    二、创建新的指针

    可通过4种方式创建新的指针:

    • UnsafeRawPointer(bitPattern: 内存地址)
    • malloc(字节数)
    • 可变原始指针,UnsafeMutableRawPointer.allocate(byteCount:字节数, alignment: 1)
    • 可变指针,UnsafeMutablePointer<泛型类型>.allocate(capacity: 泛型类型个数)
    // 新创建指针
    func testNewPointer() {
        // 1.直接传内存地址来创建一个原始指针
        var ptr = UnsafeRawPointer(bitPattern: 0x100001234)
        // 2.通过malloc来创建一个可变原始指针(可以存值)
        var ptr2 = malloc(16)
        // 修改
        ptr2?.storeBytes(of: 118, as: Int.self)
        ptr2?.storeBytes(of: 220, toByteOffset: 8, as: Int.self)
        // 读取
        print((ptr2?.load(as: Int.self))!) // 118
        print((ptr2?.load(fromByteOffset: 8, as: Int.self))!) //220
        
        // 3.通过可变原始指针分配、修改、读取内存
        var ptr3 = UnsafeMutableRawPointer.allocate(byteCount: 16, alignment: 1)
        ptr3.storeBytes(of: 30, as: Int.self)
        ptr3.advanced(by: 8).storeBytes(of: 33, as: Int.self)
        
        print(ptr3.load(as: Int.self)) // 30
        print(ptr3.advanced(by: 8).load(as: Int.self)) //33
        
        // 4.通过可变指针分配、修改、读取内存
        var ptr4 = UnsafeMutablePointer<Int>.allocate(capacity: 3)
        ptr4.initialize(to: 11)
        ptr4.successor().initialize(to: 22)
        ptr4.successor().successor().initialize(to: 33)
        
        print("第1个int = \(ptr4.pointee), 第2个int = \((ptr4 + 1).pointee), 第3个int = \((ptr4 + 2).pointee)")
        print("第1个int = \(ptr4[0]), 第2个int = \(ptr4[1]), 第3个int = \(ptr4[2])")
        
        ptr4.deinitialize(count: 3)
        ptr4.deallocate()
    }
    
    三、指针类型转换

    上述指针类型之间可以进行转换,如下:

    // 指针之间的转换
    func testPointerTransfer() {
        let ptr = UnsafeMutableRawPointer.allocate(byteCount: 16, alignment: 1)
        // 1. 通过assumingMemoryBound来转换
        ptr.assumingMemoryBound(to: Int.self).pointee = 11
        (ptr + 8).assumingMemoryBound(to: Double.self).pointee = 22
        
        // 2.通过unsafeBitCast进行忽略类型的强制转换
        // 转换为UnsafePointer<Int>类型后通过pointee访问
        let ptr_trannsfer = unsafeBitCast(ptr, to: UnsafePointer<Int>.self)
        print(ptr_trannsfer.pointee)
        let ptr_trannsfer2 = unsafeBitCast(ptr + 8, to: UnsafePointer<Double>.self)
        print(ptr_trannsfer2.pointee)
        
        // 3.UnsafeMutableRawPointer可以通过bindMemory方法转换为UnsafeMutablePointer
        let ptr222 = (ptr + 8).bindMemory(to: Double.self, capacity: 1)
        ptr222.pointee = 33.0
        print(ptr222.pointee)
        
        ptr.deallocate()
    }
    

    相关文章

      网友评论

          本文标题:Swift中指针

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