Swift超详细讲解指针

来自:网络
时间:2023-07-25
阅读:
目录

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 相同

Swift超详细讲解指针

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

Swift超详细讲解指针

例子 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

返回顶部
顶部