3

Swift5.1 - 指针Pointer

 2 years ago
source link: https://www.jianshu.com/p/8cff1ef20e8c
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Swift5.1 - 指针Pointer

12019.08.29 05:49:42字数 297阅读 1,025

使用swift提供指针类型:

  • UnsafePointer
  • UnsafeMutablePointer
  • UnsafeRawPointer
  • UnsafeMutableRawPointer

UnsafePointer / UnsafeMutablePointer用法:

使用 pointee 属性可以进行读写操作;

var age = 10
func change1(_ ptr: UnsafeMutablePointer<Int>) {
    ptr.pointee += 20
}

func change2(_ ptr: UnsafePointer<Int>) {
    print(ptr.pointee)
}

change1(&age) 
change2(&age) // 30
print(age)    // 30

UnsafeRawPointer / UnsafeMutableRawPointer

var age = 10
func change3(_ ptr: UnsafeMutableRawPointer) {
    ptr.storeBytes(of: 20, as: Int.self)
}

func change4(_ ptr: UnsafeRawPointer) {
    print(ptr.load(as: Int.self))
}

change3(&age) 
change4(&age) // 20
print(age)    // 20

获取堆空间地址

class Person {}
var person = Person()

//获取person指针的地址值
var ptr = withUnsafePointer(to: &person) { UnsafeRawPointer($0) }  

// 获取person指针的指向的地址,就是为Person的堆空间地址
var headPtr = UnsafeRawPointer(bitPattern: ptr.load(as: UInt.self))

print(ptr)
print(headPtr)
print(person)
0x00000001000031f8
0x00000001006b6340
  • withUnsafePointer 的闭包返回类型就是person变量指针的地址值(栈空间);
  • headPtr 是获取 ptr指向的地址值,就是Person实例对象的地址(堆空间);

创建 UnsafeRawPointer / UnsafeMutableRawPointer 创建指针

  1. 方式一:通过地址值创建
var ptr = UnsafeRawPointer(bitPattern: 0x0000000100003008)
var ptr = malloc(16) // UnsafeMutableRawPointer
ptr?.storeBytes(of: 10, as: Int.self) // 8字节
ptr?.storeBytes(of: 20, toByteOffset: 8, as: Int.self) // 存放在后8字节中

print( (ptr?.load(as: Int.self))! )   // 10
print( (ptr?.load(fromByteOffset: 8, as: Int.self))! ) // 20
free(ptr)
var ptr = UnsafeMutableRawPointer.allocate(byteCount: 16, alignment: 1)
ptr.storeBytes(of: 10, as: Int.self)
//ptr.advanced(by: 8).storeBytes(of: 20, as: Int.self)
(ptr + 8).storeBytes(of: 20, as: Int.self)

print( ptr.load(as: Int.self) )   // 10

print( ptr.load(fromByteOffset: 8, as: Int.self) ) // 20
print( ptr.advanced(by: 8).load(as: Int.self) )  // 20
print( (ptr + 8).load(as: Int.self) ) //20

ptr.deallocate()

fromByteOffset 与 advanced都能让指针进行偏移;创建指针后,记得释放;

UnsafePointer / UnsafeMutablePointer 创建指针

var ptr = UnsafeMutablePointer<Int>.allocate(capacity: 3)
ptr.initialize(to: 10)
ptr.successor().initialize(to: 20)
ptr.successor().successor().initialize(to: 30)

print(ptr.pointee)  // 10
print(ptr.successor().pointee) // 20
print(ptr.successor().successor().pointee) // 30

ptr.deinitialize(count: 3)
ptr.deallocate()
var ptr = UnsafeMutablePointer<Int>.allocate(capacity: 3)
ptr.initialize(to: 10)
(ptr + 1).initialize(to: 20)
(ptr + 2).initialize(to: 30)

print(ptr.pointee)  // 10
print((ptr + 1).pointee) // 20
print((ptr + 2).pointee) // 30

ptr.deinitialize(count: 3)
ptr.deallocate()

ptr表示创建3个整形的指针;initialize为初始化;successor表示每次偏移8字节(整形);

指针之间的转换

var ptr = UnsafeMutableRawPointer.allocate(byteCount: 16, alignment: 1)

// assumingMemoryBound 返回 UnsafeMutablePointer<T>类型
ptr.assumingMemoryBound(to: Int.self).pointee = 10
(ptr + 8).assumingMemoryBound(to: Int.self).pointee = 20

print( unsafeBitCast(ptr, to: UnsafePointer<Int>.self).pointee ) // 10
print( unsafeBitCast(ptr + 8, to: UnsafePointer<Int>.self).pointee ) // 20
ptr.deallocate()
  • unsafeBitCast 忽略数据类型的强制转换,不会因为数据类型的变化而改变原来的内存结构;
  • 以上都是使用整形存储在指针中,实际上存储对象,结构体等;
  • UnsafeMutableRawPointer指针+1表示一个字节;UnsafeMutablePointer+1表示泛型对象占用内存字节数+1,即下一个对象;

源代码demo


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK