Swift超详细讲解指针

从传统的C代码和与之无缝配合的Objective-C代码迁移到Swift并非小工程,我们的代码库肯定会时不时出现一些和C协作的地方,如果想要继续使用那些C API的话,了解一些基本的Swift指针操作和使用的知识会很有帮助。下面通过这篇文章一起来学习下

Swift指针Unsafe Pointer

如果不是只读,可以修改 ( 写入 ),就加一个 Mutable,

如果没有具体的类型( 通过泛型的方式 ),就加一个 Raw,

如果不是一个单独的对象 ( 指向集合类型 ),就加上 buffer.

Unsafe [ Mutable ] [ Raw ] [ Buffer ] Pointer [ ]

苹果没有编译保护的 [ 可变的 ] [没有类型的] [ 是集合的 ] 指针 [< 具体的类型 >]

对照Objective-C

  • swift 的 unsafeMutablePointer<T>: OC 的 T *
  • swift 的 unsafePointer<T>: OC 的 const T *
  • swift 的 unsafeRawPointer: OC 的 const void *
  • swift 的 unsafeMutableRawPointer: OC 的 void *

例子

例子 1, 无类型的指针

let count = 2
let stride = MemoryLayout<Int>.stride
let alignment = MemoryLayout<Int>.alignment
let byteCount = stride * count
do {
  print("Raw pointers")
  let pointer = UnsafeMutableRawPointer.allocate(
    byteCount: byteCount,
    alignment: alignment)
    // 指针的创建,与销毁
  defer {
     // 需要手动管理,指针的内存
    pointer.deallocate()
  }
  // store 存值
  pointer.storeBytes(of: 42, as: Int.self)
  // 指针需要移动 stride,才能到达下一个指针
  pointer.advanced(by: stride).storeBytes(of: 6, as: Int.self)
  // (pointer+stride).storeBytes(of: 6, as: Int.self), 这个是另一种方式
  // load 取值
  print(pointer.load(as: Int.self))
  print(pointer.advanced(by: stride).load(as: Int.self))
  // 集合的指针
  let bufferPointer = UnsafeRawBufferPointer(start: pointer, count: byteCount)
  for (index, byte) in bufferPointer.enumerated() {
    print("byte \(index): \(byte)")
  }
}

2, 具体类型的指针

具体类型的指针,可以通过指针的 pointee 属性,方便的操作 load 和 store

let count = 2
let stride = MemoryLayout<Int>.stride
let alignment = MemoryLayout<Int>.alignment
let byteCount = stride * count
do {
  print("Typed pointers")
  let pointer = UnsafeMutablePointer<Int>.allocate(capacity: count)
  pointer.initialize(repeating: 0, count: count)
  // 与上面的一样,指针的内存,需要手动管理
  defer {
    pointer.deinitialize(count: count)
    pointer.deallocate()
  }
  pointer.pointee = 42
   // 因为编译器做了优化,指针到达下一个指针,不需要移动 stride
   // 指针移动 1 ,就到了下一个指针
  pointer.advanced(by: 1).pointee = 6
  print( pointer.pointee )
  print(pointer.advanced(by: 1).pointee)
  let bufferPointer = UnsafeBufferPointer(start: pointer, count: count)
  for (index, value) in bufferPointer.enumerated() {
    print("value \(index): \(value)")
  }
}

例子 3: 通过绑定内存,来做指针的转化

bindMemory

let count = 2
let stride = MemoryLayout<Int>.stride
let alignment = MemoryLayout<Int>.alignment
let byteCount = stride * count
do {
  print("Converting raw pointers to typed pointers")
  let rawPointer = UnsafeMutableRawPointer.allocate(
    byteCount: byteCount,
    alignment: alignment)
  defer {
    rawPointer.deallocate()
  }
  // 这一步,将任意指针,转化为类型指针
  let typedPointer = rawPointer.bindMemory(to: Int.self, capacity: count)
  typedPointer.initialize(repeating: 0, count: count)
  defer {
    typedPointer.deinitialize(count: count)
  }
  typedPointer.pointee = 42
  typedPointer.advanced(by: 1).pointee = 6
   // 看结果
  print(typedPointer.pointee)
  print(typedPointer.advanced(by: 1).pointee)
  let bufferPointer = UnsafeBufferPointer(start: typedPointer, count: count)
  for (index, value) in bufferPointer.enumerated() {
    print("value \(index): \(value)")
  }
}

例子 4, 查看指针的字节

struct Demo{
  let number: UInt32
  let flag: Bool
}
do {
  print("Getting the bytes of an instance")
  var one = Demo(number: 25, flag: true)
  withUnsafeBytes(of: &one) { bytes in
    for byte in bytes {
      print(byte)
    }
  }
}

例子 4.1, 指针的字节, 算 check sum

struct Demo{
  let number: UInt32
  let flag: Bool
}
do {
  print("Checksum the bytes of a struct")
  var one = Demo(number: 25, flag: true)
  let checksum = withUnsafeBytes(of: &one) { (bytes) -> UInt32 in
    return ~bytes.reduce(UInt32(0)) { $0 + numericCast($1) }
  }
  print("checksum", checksum) //  checksum 4294967269
}

checeSum 的使用,分为 checeSum 的计算与校验

本文简单描述 checeSum 的计算

数据块,分为 n 个包, size 相同

IiBzcmM9

拿包的字节,计算 checkSum, checkSum 的大小限制在包的 size

IiBzcmM9

例子 5, 获取变量的指针

var cat = "fly"
// 返回的是,闭包中的参数
// withUnsafePointer , 把闭包里面的结果,rethrow 出去 ( 相当于 return 出来 )
let warrior = withUnsafePointer(to: &cat, { $0 })
print(warrior.pointee)

例子 6, 指向多个元素的指针

struct Cat{
    var habit = "eat"
    var paws = 6
    var name = "load"
}
let ptr = UnsafeMutablePointer<Cat>.allocate(capacity: 2) // 指向两个 Cat 结构体
ptr.initialize(repeating: Cat(), count: 2)
defer{
    ptr.deinitialize(count: 2)
    ptr.deallocate()
}
var one = Cat()
one.paws = 8
ptr[1] = one
// 以下两个等价
print(ptr[0])
print(ptr.pointee)
// 下面 3 个等价
print(ptr[1])
print((ptr + 1).pointee)
print(ptr.successor().pointee)

例子 7: 元素组合的探索

var pair = (66, 666)
func test(ptr: UnsafePointer<Int>){
    print(ptr.pointee)
    print(ptr.successor().pointee)
}
withUnsafePointer(to: &pair) { (tuplePtr: UnsafePointer<(Int, Int)>) in
    // 假定内存绑定,不需要经过内存检查
    test(ptr: UnsafeRawPointer(tuplePtr).assumingMemoryBound(to:Int.self))
}

参考了 Unsafe Swift: Using Pointers and Interacting With C

到此这篇关于Swift超详细讲解指针的文章就介绍到这了,更多相关Swift指针内容请搜索编程学习网以前的文章希望大家以后多多支持编程学习网!

本文标题为:Swift超详细讲解指针