Ios Swift:如何将偏移量添加到memcpy(…)

Ios Swift:如何将偏移量添加到memcpy(…),ios,arrays,performance,swift,memcpy,Ios,Arrays,Performance,Swift,Memcpy,如何为memcpy(…)调用添加数组偏移量 我有一个字符串数组: var source = ["a","b","c","d"] var dest = [String](count:n, repeatedValue: "") memcpy(&dest, source, UInt(2 * sizeof(String)) 此副本[“a”、“b”]发送至目的地。很明显。 如何复制[“b”、“c”]?请勿在对象上使用memcpy或其他低级“c”运算符。由于许多原因,这是行不通的 使用切片操作符:

如何为memcpy(…)调用添加数组偏移量

我有一个
字符串数组

var source = ["a","b","c","d"]
var dest = [String](count:n, repeatedValue: "")
memcpy(&dest, source, UInt(2 * sizeof(String))
此副本[“a”、“b”]发送至目的地。很明显。
如何复制[“b”、“c”]?

请勿在对象上使用memcpy或其他低级“c”运算符。由于许多原因,这是行不通的

使用切片操作符:

var source = ["a","b","c","d"]
var dest = Array(source[1...2])
println("dest: \(dest)")
输出:

目的地:[b,c]

正确处理Unicode:

var source = ["First of all, there's something none of the writers seem to have understood: an array of object (here String instances) do not store the content but a reference to this object. Therefore UTF-8, UTF-16, whatever has nothing to do with it. What the backing array actually contains is pointers (ie addresses == unsigned integers). Aside from that, unless an array in swift is an actual array in memory, you shouldn't use memcpy on it, even more so if it is backed by an NSArray!

Nonetheless, to answer the original question that seems to be working perfectly and makes me think that in this case the Swift Array is a contiguous zone of memory here is what you should do:

source and dest are pointers to contiguous memory zones: the first object being at the base address, the second @+sizeof(type), the nth element at @+(n-1)*sizeof(type).

All you have to do is specify the write offset for dest, in your particular case 0, and the offset in source, in your case 1.

I'm still new to Swift, and use of methods with "Unsafe" in the name still worries me, but I'm fairly sure this is a usable technique for calling memcpy() and specifying an offset for the destination and/or source address. But this only works for byte arrays, i.e., [UInt8]. Definitely not for strings, as explained by @zaph.

public class SystemMisc {

   /// Wrapper for the memcpy() method that allows specification of an offset for the destination
   /// and/or the source addresses.
   ///
   /// This version for when destination is a normal Swift byte array.
   ///
   /// - Parameters:
   ///   - destPointer:    Address for destination byte array, typically Swift [UInt8].
   ///   - destOffset:     Offset to be added to the destination address, may be zero.
   ///   - sourcePointer:  Address for source byte array, typically Swift [UInt8].
   ///   - sourceOffset:   Offset to be added to the source address, may be zero.
   ///   - byteLength:     Number of bytes to be copied.
   public static func memoryCopy(_ destPointer : UnsafeRawPointer, _ destOffset : Int,
                                 _ sourcePointer : UnsafeRawPointer, _ sourceOffset : Int,
                                 _ byteLength : Int) {

      memoryCopy(UnsafeMutableRawPointer(mutating: destPointer), destOffset,
                 sourcePointer, sourceOffset, byteLength)
   }


   /// Wrapper for the memcpy() method that allows specification of an offset for the destination 
   /// and/or the source addresses.
   ///
   /// This version for when destination address is already available as an UnsafeMutableRawPointer, 
   /// for example if caller has used UnsafeMutableRawPointer() to create it or is working with 
   /// unmanaged memory. The destPointer argument may also be a converted pointer, as done by the 
   /// above wrapper method.
   ///
   /// - Parameters:
   ///   - destPointer:    Address for destination byte array, see above notes.
   ///   - destOffset:     Offset to be added to the destination address, may be zero.
   ///   - sourcePointer:  Address for source byte array, typically Swift [UInt8].
   ///   - sourceOffset:   Offset to be added to the source address, may be zero.
   ///   - byteLength:     Number of bytes to be copied.
   public static func memoryCopy(_ destPointer : UnsafeMutableRawPointer, _ destOffset : Int,
                                 _ sourcePointer : UnsafeRawPointer, _ sourceOffset : Int,
                                 _ byteLength : Int) {

      memcpy(destPointer.advanced(by: destOffset),
             sourcePointer.advanced(by: sourceOffset),
             byteLength)
   }
}

var-source=[”首先,有一点作者似乎都不理解:对象数组(这里是字符串实例)不存储内容,而是存储对该对象的引用。因此UTF-8、UTF-16,与此无关。支持数组实际上包含的是指针(即地址==无符号整数).除此之外,除非swift中的数组是内存中的实际数组,否则不应在其上使用memcpy,如果它有NSArray支持,则更应如此

尽管如此,要回答最初的问题,它似乎工作得很好,让我认为在这种情况下,Swift数组是一个连续的内存区域,您应该这样做:

source和dest是指向连续内存区域的指针:第一个对象位于基址,第二个@+sizeof(type),第n个元素位于@+(n-1)*sizeof(type)


您所要做的就是指定dest的写入偏移量(在您的特定情况下为0),以及source中的偏移量(在您的情况下为1)。

我对Swift还是新手,使用名称中带有“Unsafe”的方法仍然让我担心,但我相当肯定这是调用memcpy()的一种可用技术和为目标和/或源地址指定偏移量。但这仅适用于字节数组,即[UInt8]。绝对不适用于字符串,如@zaph所解释

  // Test the memoryCopy() method, using extra UnsafeMutableRawPointer conversion

  let destArray1 : [UInt8] = [ 0, 1, 2, 3 ]  // Note - doesn't need to be var
  let sourceArray1 : [UInt8] = [ 42, 43, 44, 45 ]

  SystemMisc.memoryCopy(destArray1, 1, sourceArray1, 1, 2)

  assert(destArray1[0] == 0 && destArray1[1] == 43 && destArray1[2] == 44 && destArray1[3] == 3)


  // Test the memoryCopy() method, providing UnsafeMutableRawPointer for destination

  var destArray2 : [UInt8] = [ 0, 1, 2, 3 ]
  let sourceArray2 : [UInt8] = [ 42, 43, 44, 45 ]

  let destArray2Pointer = UnsafeMutableRawPointer(&destArray2)

  SystemMisc.memoryCopy(destArray2Pointer, 1, sourceArray2, 1, 2)

  assert(destArray2[0] == 0 && destArray2[1] == 43 && destArray2[2] == 44 && destArray2[3] == 3)
下面是一些测试代码:


谢谢你的回答。这对我很有帮助。这是一个好的、快速的方法,但仍然比memcpy()慢一点.@user2245247 memcpy不一定有效,对于unicode表情符号、代理项对和标志(其中字符是多个UTF-16单位)肯定无效。虽然字符串的实现似乎是UTF-16,但可能会发生变化。Swift代码比memcpy慢,因为它正确处理大小为多个UTF-16单位的字符。PerDonald Knuth:“过早优化是万恶之源”。你介意看看我下面的答案吗?如果你认为这太危险,请告诉我。这样做的目的是什么?但是Swift不会让你在memcpy()的操作数上指定偏移量call.string是值类型,而不是引用。另一方面,尝试使用memcpy复制字符串(如果您设法做到了这一点)会复制位,但以后会给您带来严重的麻烦。尽管我发现上面的答案大部分是有效的,但从另一方面来说,aik
数组
不能保证是一个连续的内存区域
 连续数组
is@bartlomiej.n你是对的,参考数组的文档,这取决于它的支持。Swift我的意思不是NSArray。顺便说一句,谢谢你提供的信息。谢谢你实际回答这个问题。是的,这是非常危险的,不应该使用,但这是警告的目的。即使你如果你发现没有合法的用例,在引擎盖下看一眼仍然很有趣。只有我的两分钱。