我实际上已经在 stackoverflow 和其他地方广泛搜索了这个。 大多数问题是关于 [UInt8] 到 String 或 [UInt8] 到 type_a(不是数组)。
澄清一下,我想要一个 type_a 数组。获取它的指针并告诉 swift 将 type_b (size_of) 的下 n 次迭代视为 type_b 的数组。
我试过 https://stackoverflow.com/a/26954091/5276890 的变体这没有用。那里的评论让我找到了 https://stackoverflow.com/a/42255468/5276890 . withMemoryRebound 似乎是正确的方法,但我找不到正确的调用。
这是我正在做的将 [UInt8] 转换为 [UInt32.bigEndian] 的示例代码,既是为了澄清,也是为了以防它有用(不太可能)
var intData = [UInt32]()
let M = UInt32(256*256*256)
var m = M
var bigE:UInt32 = 0
for i in 0..<data.count {
bigE += UInt32(data[i]) * m
if m == 1 {
intData.append(bigE)
bigE = 0
m = M
} else {
m = m/256
}
}
<免责声明+咆哮>
我不得不承认我永远无法弄清楚整个 closures+withUnsafe* 语法和主要在线使用的模式并修改它们。我会花时间学习这个,只要语言作者决定并确定一种特定的语法:(
免责声明+咆哮>
最佳答案
- 使用
withUnsafeBufferPointer
获取指向元素的指针 源数组的存储。 - 使用
withMemoryRebound
将指针“重新解释”为指向 到目标类型的元素。 - 使用
Array(UnsafeBufferPointer(...)
创建一个数组 目标类型。
例子:
let source: [UInt16] = [1, 2, 3, 4]
let dest = source.withUnsafeBufferPointer {
$0.baseAddress!.withMemoryRebound(to: UInt32.self, capacity: 2) {
Array(UnsafeBufferPointer(start: $0, count: 2))
}
}
print(dest) // [131073, 262147]
或者作为通用函数:
func convertArray<S, T>(_ source: [S], to: T.Type) -> [T] {
let count = source.count * MemoryLayout<S>.stride/MemoryLayout<T>.stride
return source.withUnsafeBufferPointer {
$0.baseAddress!.withMemoryRebound(to: T.self, capacity: count) {
Array(UnsafeBufferPointer(start: $0, count: count))
}
}
}
例子:
let source: [UInt16] = [1, 2, 3, 4]
let dest = convertArray(source, to: UInt32.self)
print(dest) // [131073, 262147]
如果你只需要一个(临时的)view 数组存储解释
在另一种类型中,您可以避免 Array
创建
并使用 UnsafeBufferPointer
(这是一个 Collection
和
有类似数组的方法)而不复制数据:
source.withUnsafeBufferPointer {
$0.baseAddress!.withMemoryRebound(to: UInt32.self, capacity: 2) {
let u32bufptr = UnsafeBufferPointer(start: $0, count: 2)
// ... Operate on u32bufptr ...
for elem in u32bufptr { print(elem) }
}
}
关于arrays - 将 [type_a] 转换为 [type_b],我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43673868/