一尘不染

Swift中的指针,指针算术和原始数据

swift

我的应用程序使用某种复杂的不可变数据结构,该结构以二进制文件编码。我需要在字节级别访问它,避免任何复制。通常,我将使用C或C
++指针算术和类型转换来访问和解释原始字节值。我想对Swift做同样的事情。

我发现以下作品:

class RawData {
    var data: NSData!

    init(rawData: NSData) {
      data = rawData
    }

    func read<T>(byteLocation: Int) -> T {
      let bytes = data.subdataWithRange(NSMakeRange(byteLocation, sizeof(T))).bytes
      return UnsafePointer<T>(bytes).memory
    }

    func example_ReadAnIntAtByteLocation5() -> Int {
      return read(5) as Int
    }
}

但是,我不确定它的效率如何。每次我调用对象时都要做data.subdataWithRangeNSMakeRange分配对象,或者它们只是用于处理指针的语法糖吗?

在Swift中有更好的方法吗?

编辑:

我创建了一个小的Objective-C类,该类只封装了一个将指针偏移给定字节数的函数:

@implementation RawDataOffsetPointer

inline void* offsetPointer(void* ptr, int bytes){
    return (char*)ptr + bytes;
}

@end

如果我在桥接标题中包含此类,则可以将read方法更改为

func read<T>(byteLocation: Int) -> T {
  let ptr = offsetPointer(data.bytes, CInt(byteLocation))
  return UnsafePointer<T>(ptr).memory
}

这不会从我的缓冲区复制数据,也不会分配其他对象。

但是,如果可能的话,从Swift执行一些指针算术仍然是很好的。


阅读 252

收藏
2020-07-07

共1个答案

一尘不染

如果您只想直接UnsafePointer<T>进行操作,可以进行算术操作:

   let oldPointer = UnsafePointer<()>
   let newPointer = oldPointer + 10

您也可以像这样投射一个指针(UnsafePointer<()>等效于void *

   let castPointer = UnsafePointer<MyStruct>(oldPointer)
2020-07-07