【问题标题】:Memset to UnsafeMutablePointer<UInt8> in swiftMemset 快速转换为 UnsafeMutablePointer<UInt8>
【发布时间】:2015-05-04 02:02:39
【问题描述】:

我对@9​​87654321@ 类型的变量有疑问。

我有这个工作代码要分配并在 Swift 中将所有 UInt8 数组设置为零。
var bits = UnsafeMutablePointer&lt;UInt8&gt;(calloc(width * height, 8))

问题是我不想使用 calloc 方法。我有这个代码来分配数组
var bits = UnsafeMutablePointer&lt;UInt8&gt;.alloc(width * height)

但我找不到将所有内存设置为零的方法。

我知道我可以做到这一点,但我认为这不是最好的方法。

for index in 0..< (width * height) {
    bits[index] = 0
}

【问题讨论】:

  • "但我认为这不是最好的方法" 抱歉,你能澄清一下它有什么问题吗?我的意思是,calloc 也必须循环内存,那有什么区别?
  • 没有错。它可以工作,但我只是在寻找像memset 这样的函数来初始化数组。我用谷歌搜索了几个小时,然后在 Stack Overflow 中搜索,但没有成功。现在我正在使用calloc 方法。
  • 我想你可以说bits.initializeFrom(Array&lt;UInt8&gt;(count: width * height, repeatedValue: 0))
  • @matt。是的,这就是我一直在寻找的。这比我想象的要容易。
  • 好吧,如果你真的喜欢它,我会给它作为答案。 :)

标签: swift pointers allocation


【解决方案1】:

正如@matt 建议的那样,您可以使用initializeFrom 来初始化内存。我会为此使用 Repeat 集合类型,因为它避免了任何临时分配:

var bits = UnsafeMutablePointer<UInt8>.alloc(width * height)
bits.initializeFrom(Repeat(count: width * height, repeatedValue: 0))

(注意,Repeat的值的类型不需要给出,可以从bits的类型推断出来)

如果您发现自己经常这样做,可能值得为UnsafeMutablePointer 创建一个类似calloc 的扩展:

extension UnsafeMutablePointer {
    // version that takes any kind of type for initial value
    static func calloc(num: Int, initialValue: T) -> UnsafeMutablePointer<T> {
        let ptr = UnsafeMutablePointer<T>.alloc(num)
        ptr.initializeFrom(Repeat(count: num, repeatedValue: initialValue))
        return ptr
    }

    // convenience version for integer-literal-creatable types 
    // that initializes to zero of that type
    static func calloc<I: IntegerLiteralConvertible>
      (num: Int) -> UnsafeMutablePointer<I> {
        return UnsafeMutablePointer<I>.calloc(num, initialValue: 0)
    }
}

// creates 100 UInt8s initialized to 0
var bits = UnsafeMutablePointer<UInt8>.calloc(100)

【讨论】:

  • 这会和c calloc一样优化吗?
【解决方案2】:

你可以说:

bits.initializeFrom(Array<UInt8>(count: width * height, repeatedValue: 0))

我猜想以这种方式复制内存有一些潜在的效率。但是,我们暂时制作阵列当然效率低下。 [注意:AirspeedVelocity 的回答显示了一种避免这种情况的方法。]

就个人而言,我最喜欢你原来的循环,特别是如果你写得更紧凑,像这样:

(0 ..< (width*height)).map {bits[$0] = 0}

【讨论】:

  • 是的,它不是memset,但它是另一种方式。
  • 我会这样写你的循环:(0 ..&lt; (width*height)).map {bits[$0] = 0}我个人更喜欢这种方式。
  • 您可以使用Repeat 序列:bits.initializeFrom(Repeat(count: 100, repeatedValue: 0)),而不是创建一个数组来执行此操作以再次丢弃它。
  • @AirspeedVelocity 但是Repeat 是懒惰的吗?如果没有,我看不到优势。您仍然会创建width*height 零的集合,只是为了再次将其丢弃。
  • @matt 取决于你所说的惰性......它是一个集合类型,起始索引为 0,结束索引为 count,并且每次都返回相同的数字。与数组不同,它不会在内存中分配count 条目的区域,它只需要两个参数并存储它们。所以理论上它比数组方法更有效(虽然,很可能,使用优化器,它们实际上会产生相同的汇编代码)
猜你喜欢
  • 1970-01-01
  • 2016-03-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-04-04
  • 1970-01-01
  • 1970-01-01
  • 2019-10-20
相关资源
最近更新 更多