指针

四种指针类型

@frozen struct UnsafePointer<Pointee>    相当于const Pointee *(常量指针,顾名思义无法修改) 其中Pointee是个泛型,他可以指代类型,比如UnsafePointer<Int>就是 const Int *

@frozen struct UnsafeMutablePointer<Pointee>    相当于 Pointee * 就是普通指针,能修改的

@frozen struct UnsafeRawPointer   相当于 const void * 无符号指针,不能修改

@frozen struct UnsafeMutableRawPointer 相当于void * 能修改

 

从属性上看所有的指针都是结构体类型,和Unsafe,一般unsafe就比较底层,平时调试使用,正式开发最好别用

var a:Int = 10
func test(_ point:UnsafePointer<Int>) {
    print(point)     //0x000000010000c1f8
    print(point.pointee)  //10
}
test(&a)

可以看到这个指针就是指向a地址的指针

var a:Int = 10
func test(_ point:UnsafeMutablePointer<Int>) {
    print(point)     //0x000000010000c1f8
    point.pointee = 20
    print(point.pointee)  //20
}
test(&a)
print(a) //  20

然后换成UnsafeMutablePointer就可以修改内容

再创建个类发现要改成UnsafeMutablePointer<Person>,而且还要往函数传值也很麻烦

extension Int
{
    var pointer:UnsafePointer<Int>
    {
        mutating get{ withUnsafePointer(to: &self, { $0 }) }
    }
}
var a:Int = 10
print(a.pointer)  //0x000000010000c1f8

核心代码就这一句withUnsafePointer(to: &self, { $0 })  其中{$0}是一个闭包(详见闭包),用处就是把第一个参数直接返回,这第一个参数就是指针,这个闭包里面可以自定义内容,一般来说,系统返回的指针就够用了

这样获取的都是变量本身的地址,而对于类来说,信息是存在堆空间的,而这个里面只是存储着那个的地址,所以就有了根据地址获取指针

var p:Person = Person()
let pointer = withUnsafePointer(to: &p, { UnsafeRawPointer($0) })
let cPointer = UnsafeMutableRawPointer(bitPattern: pointer.load(as: UInt.self))
print(cPointer)

至于这里为啥用UInt,原因就是这里获取的只是指向堆空间的指针的那个指针地址,这个地址实际上是Int类型的,堆空间的内容才是Person类型,为啥使用UnsafeRawPonter强制转换的原因也在这,因为从编译器里面看这个指针是Person类型的,而实际存储的值又是一个Int的地址值,所以无法用unsafePointer

所以可以得出结论,UnsafePointer系列的是常规指针,就是指向变量的地址,而要指向堆空间的对象指针,则需要用UnsafeRawPointer系列指针来完成

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值