Swift:如何向memcpy添加偏移量(...)

时间:2014-08-01 11:36:52

标签: ios arrays performance swift memcpy

如何为memcpy(...)调用添加数组的偏移量?

我有String的数组:

var source = ["a","b","c","d"]
var dest = [String](count:n, repeatedValue: "")
memcpy(&dest, source, UInt(2 * sizeof(String))

此副本[" a"," b"]为dest。我很明显。 我如何复制[" b"," c"]?

3 个答案:

答案 0 :(得分:5)

不要使用memcpy或其他低级" C"对象上的运算符。这不会有多种原因。

使用切片运算符:

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

输出:

  

dest:[b,c]

正确处理Unicode:

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

输出:

  

dest:[,a]

答案 1 :(得分:1)

我还是Swift的新手,在名称中使用“Unsafe”的方法仍然让我担心,但我很确定这是一种可用的技术,用于调用memcpy()并指定目标的偏移量/或源地址。但这仅适用于字节数组,即[UInt8]。绝对不是字符串,正如@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)
   }
}

这是一些测试代码:

  // 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)

答案 2 :(得分:0)

首先,编者似乎没有理解:对象数组(此处为String实例)不存储内容,而是存储对此对象的引用。因此UTF-8,UTF-16,无论与它无关。支持数组实际包含的是指针(即地址==无符号整数)。除此之外,除非swift中的数组是内存中的实际数组,否则不应该在其上使用memcpy,如果它由NSArray支持则更是如此!

尽管如此,回答原本似乎完美运行的问题并让我觉得在这种情况下,Swift数组是一个连续的内存区域,这是你应该做的:

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

您需要做的就是指定dest的写入偏移量,在特定情况下为0,在源代码中指定偏移量,在您的情况下为1。