印象: 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 相同

截屏2022-06-14 下午4.57.02.png

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

截屏2022-06-14 下午5.00.15.png

例子 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
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值