Swift中有4个指针类型:UnsafePointer
、UnsafeMutablePointer
、UnsafeRawPointer
、UnsafeMutableRawPointer
,通过指针可以直接修改指向的内存数据,下面简单介绍下它们的几个常见用法。
一、从已有的变量获取指针
- 获取指向变量或者指向对象的指针、读写指向变量的值的方式如下:
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)
}
- 作为函数参数时,可变类型的指针
UnsafeMutablePointer
和UnsafeRawPointer
与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()
}
网友评论