Swift3.0 指针

Swift3.0 指针

最近试着用Swift基于AudioQueue写一个音乐播放器,但是AudioQueue的API都是C函数,避免不了操作指针。经常卡在指针上,于是决定先静下心来学习一下Swift中的指针。baidu了很多,但是没有系统讲解Swift指针的文章,一边学一边记录,写下这些作为积累。这次学习分为四个部分:UnsafePointer, UnsafeMutablePointer, UnsafeRawPointer, UnsafeMutableRawPointer。有不对的地方欢迎指出!

在Swift中,指针由结构体 struct UnsafePointer<Pointee>struct UnsafeMutablePointer<Pointee> 表示,但是不能通过”&”获取一个UnsafePointerUnsafeMutablePointer的实例,只能作为inout参数使用。UnsafePointer相对于UnsafeMutablePointer,其所指向的地址的值是不可变的

一、UnsafeMutablePointer

UnsafeMutablePointe引用的内存有三种状态:

1. Not Allocated

2. Allocated but not initialized

3. Allocated and initialized

只有在状态3时,可以安全的使用pointee属性来setget

1.初始化

allocate() initialize() deinitialize deallocate() 这四个方法来管理这个指针,并确保指针的pointee不会出错

(1) allocate
let a_unsafe_mutable_pointer = UnsafeMutablePointer<Int>.allocate(capacity: 0)

Tips:

1. 需要指明要声明的指针类型

2. allocate是静态方法

(2) initialize
a_unsafe_mutable_pointer.initialize(to: 5)
//或
a_unsafe_mutable_pointer.pointee = 5

这两种方法的结果是相同的

(3) deinitialize
a_unsafe_mutable_pointer.deinitialize(count: 1)

该方法貌似没有真正deintialize,只是返回了一个指向相同地址的UnsafeMutableRawPointer,并且a_unsafe_mutable_pointer.pointee仍然是可以正常使用

(4) deallocate
a_unsafe_mutable_pointer.deallocate(capacity: 1)

此时a_unsafe_mutable_pointer不可用了。

2.互相转化

(1) UnsafeMutablePointer -> Swift
let a : Int = a_unsafe_mutable_pointer.pointee
(2) Swift -> UnsafeMutablePointer
let a : UnsafeMutablePointer = &a 

以上代码是错误的,只能作为函数参数使用,如下所示

func printPointer(ptr:UnsafeMutablePointer<Int>) {
        print("UnsafeMutablePointer:\(ptr)")
        print("pointee:\(ptr.pointee)")
}
printPointer(ptr:&a)

3.暂时绑定

将该内存暂时绑定为一种类型,例子中将Int型绑定为Int8

a_unsafe_mutable_pointer.initialize(to: 0x0102030A)
a_unsafe_mutable_pointer.withMemoryRebound(to: Int8.self, capacity: 1, {
    ptr in
    print(String(ptr.pointee,radix:16)) //1
    print(String(ptr.advanced(by: 1).pointee,radix:16)) //2
    print(String(ptr.advanced(by: 2).pointee,radix:16)) //3
    print(String(ptr.advanced(by: 3).pointee,radix:16)) //a
})

二、UnsafePointer

  1. UnsafePointer中的pointee属性只能get不能set
  2. UnsafePointer中没有allocate方法。

1.初始化

let a_unsafe_pointer = UnsafePointer<Int>.init(a_unsafe_mutable_pointer)

可以由UnsafeMutablePointerOpaquePointer或其他UnsafePointer创建一个UnsafePointer指针。其他与UnsafeMutablePointer类似

2.互相转换

(1) UnsafeMutablePointer -> UnsafePointer
let a_unsafe_pointer = UnsafePointer<Int>.init(a_unsafe_mutable_pointer)
(2) UnsafePointer -> UnsafeMutablePointer
let a_unsafe_mutable_pointer = UnsafePointer<Int>.init(mutating:a_unsafe_pointer)
(3) UnsafePointer -> Swift
let a : Int = a_unsafe_pointer.pointee
(4) Swift -> UnsafePointer

UnsafeMutablePointer类似,只能作为函数参数引用

3.withUnsafePointer方法

withUnsafePointer方法可以直接使用指针,但是不能改变pointee的值

var a = 0
var b = a
a = withUnsafePointer(to: &a, {
        ptr in
        return ptr.pointee + 2 
        //此时,新开辟空间,令a指向该地址,其值为2
        //b仍指向a原来的地址,值为0
})

var _ = withUnsafePointer(to: &b, {
            ptr in
            let size = MemoryLayout<Int>.size //8
            //advance(by:Int)移动指针到a
            let movedPointer = ptr.advanced(by: -size) 
            print("b:\(ptr.pointee)") //b = 0
            print("a:\(movedPointer.pointee)") //a = 2
        })

三、UnsafeMutableRawPointer

UnsafeMutableRawPointer按我的理解就是无类型的原始指针

1.分配内存

var size = MemoryLayout<Int>.size
//其中alignTo是开辟内存中的对齐,不是很了解,貌似会影响效率,太底层了,不太懂
var a_unsafe_mutable_raw_pointer = UnsafeMutableRawPointer.allocate(bytes: size, alignedTo: size)

这时,这个a_unsafe_mutable_raw_pointer感觉没啥用,还是需要转换为UnsafeMutablePointer来对内存进行操作。

2.初始化

初始化内存为Int类型,并赋值为1

a_unsafe_mutable_raw_pointer.initializeMemory(as: Int.self, to: 1)

3.绑定UnsafeMutablePointer

绑定了UnsafeMutablePointer,使用UnsafeMutablePointer才能对内存进行赋值,有两种方法绑定:

(1) bindMemory()

该方法绑定内存为指定类型并返回一个UnsafeMutablePointer<指定类型>的指针

var a_unsafe_mutable_pointer = a_unsafe_mutable_raw_pointer.bindMemory(to: Int.self, capacity: 1)

(2) assumingMemoryBound()

该方法意思是直接转换这个原始指针为一个UnsafeMutablePointer<指定类型>的指针

var a_unsafe_mutable_pointer = a_unsafe_mutable_raw_pointer.assumingMemoryBound(to: Int.self)

-
这样,就可以使用这个a_unsafe_mutable_pointer进行其他操作了。

4.deallocate

最后,需要释放内存,首先要deinitialize,再deallocate

a_unsafe_mutable_pointer.deinitialize()
a_unsafe_mutable_raw_pointer.deallocate(bytes: size, alignedTo: size)

5.转换

(1) Swift -> UnsafeMutableRawPointer

var a = 10
var ptr = UnsafeMutableRawPointer(&a)

(2) UnsafeMutableRawPointer -> Swift

其过程应当为UnsafeMutableRawPointer转换为UnsafeMutablePointer,再由UnsafeMutablePointer转换为Swift指针

四、UnsafeRawPointer

UnsafeRawPointer只能由其他指针用init方法得到,与UnsafePointer类似,没有allocate静态方法。但是,与UnsafeMutableRawPointer类似的有两种绑定方法,绑定成UnsafePointer指针。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值