UnsafePointer
声明
@frozen struct UnsafePointer<Pointee>
概述
您使用UnsafePointer
类型的实例来访问内存中特定类型的数据。指针可以访问的数据类型是指针的Pointee
类型。 UnsafePointer
不提供自动内存管理或对齐保证。您负责通过不安全的指针处理您使用的任何内存的生命周期,以避免泄漏或未定义的行为。
您手动管理的内存可以是特定类型的untyped
或bound
。您使用UnsafePointer
类型来访问和管理已绑定到特定类型的内存。
了解指针的内存状态
UnsafePointer
实例引用的内存可以处于多种状态之一。许多指针操作只能应用于内存处于特定状态的指针——您必须跟踪正在使用的内存的状态,并了解不同操作执行的对该状态的更改。内存可以是无类型的和未初始化的,绑定到一个类型但未初始化,或者绑定到一个类型并初始化为一个值。最后,先前分配的内存可能已被释放,留下现有指针引用未分配的内存。
未初始化的内存
刚刚通过类型化指针分配或已取消初始化的内存处于uninitialized
状态。必须先初始化未初始化的内存,然后才能访问它以进行读取。
初始化内存
Initialized
内存具有可以使用指针的 pointee
属性或通过下标表示法读取的值。在下面的示例中,ptr
是一个指向内存的指针,初始化为 23
:
let ptr: UnsafePointer<Int> = ...
// ptr.pointee == 23
// ptr[0] == 23
以不同类型访问指针的内存
通过UnsafePointer
实例访问内存时,Pointee
类型必须与内存的绑定类型一致。如果您确实需要将绑定到一种类型的内存作为不同类型访问,Swift 的指针类型提供了type-safe 方法来临时或永久更改内存的绑定类型,或者直接从原始内存加载类型化实例。
分配有八字节内存的 UnsafePointer<UInt8>
实例 uint8Pointer
将用于以下示例。
let uint8Pointer: UnsafePointer<UInt8> = fetchEightBytes()
当您只需要临时以不同类型访问指针的内存时,请使用withMemoryRebound(to:capacity:)
方法。例如,您可以使用此方法调用 API,该 API 需要指向与您的指针的 Pointee
布局兼容的不同类型的指针。下面的代码临时将uint8Pointer
引用的内存从UInt8
重新绑定到Int8
,以调用导入的Cstrlen
函数。
// Imported from C
func strlen(_ __s: UnsafePointer<Int8>!) -> UInt
let length = uint8Pointer.withMemoryRebound(to: Int8.self, capacity: 8) {
return strlen($0)
}
// length == 7
当您需要将内存永久重新绑定到不同类型时,首先获取指向内存的原始指针,然后在原始指针上调用bindMemory(to:capacity:)
方法。以下示例将 uint8Pointer
引用的内存绑定到 UInt64
类型的一个实例:
let uint64Pointer = UnsafeRawPointer(uint8Pointer)
.bindMemory(to: UInt64.self, capacity: 1)
在将 uint8Pointer
引用的内存重新绑定到 UInt64
后,作为 UInt8
实例访问该指针的引用内存是未定义的。
var fullInteger = uint64Pointer.pointee // OK
var firstByte = uint8Pointer.pointee // undefined
或者,只要绑定类型和目标类型是普通类型,您就可以访问相同的内存作为不同类型,而无需通过非类型化内存访问重新绑定。将指针转换为 UnsafeRawPointer
实例,然后使用原始指针的 load(fromByteOffset:as:)
方法读取值。
let rawPointer = UnsafeRawPointer(uint64Pointer)
let fullInteger = rawPointer.load(as: UInt64.self) // OK
let firstByte = rawPointer.load(as: UInt8.self) // OK
执行类型化指针算术
具有类型化指针的指针算术以指针的Pointee
类型的步长计数。当您添加到 UnsafePointer
实例或从 UnsafePointer
实例减去时,结果是相同类型的新指针,偏移量为 Pointee
类型的实例数。
// 'intPointer' points to memory initialized with [10, 20, 30, 40]
let intPointer: UnsafePointer<Int> = ...
// Load the first value in memory
let x = intPointer.pointee
// x == 10
// Load the third value in memory
let offsetPointer = intPointer + 2
let y = offsetPointer.pointee
// y == 30
您还可以使用下标表示法来访问内存中特定偏移量的值。
let z = intPointer[2]
// z == 30
隐式转换和桥接
当使用 UnsafePointer
参数调用函数或方法时,您可以传递该特定指针类型的实例,传递兼容指针类型的实例,或使用 Swift 的隐式桥接来传递兼容指针。
例如,以下代码示例中的 printInt(atAddress:)
函数需要一个 UnsafePointer<Int>
实例作为其第一个参数:
func printInt(atAddress p: UnsafePointer<Int>) {
print(p.pointee)
}
与 Swift 中的典型情况一样,您可以使用 UnsafePointer
实例调用 printInt(atAddress:)
函数。此示例将 intPointer
(指向 Int
值的指针)传递给 print(address:)
。
printInt(atAddress: intPointer)
// Prints "42"
因为可变类型指针在作为参数传递时可以隐式转换为具有相同Pointee
类型的不可变指针,所以您也可以使用UnsafeMutablePointer
实例调用printInt(atAddress:)
。
let mutableIntPointer = UnsafeMutablePointer(mutating: intPointer)
printInt(atAddress: mutableIntPointer)
// Prints "42"
或者,您可以使用 Swift 的 implicit bridging
将指针传递给实例或数组的元素。以下示例使用 inout 语法传递指向 value
变量的指针:
var value: Int = 23
printInt(atAddress: &value)
// Prints "23"
当您将数组作为参数传递时,会隐式创建指向数组元素的不可变指针。此示例在调用 printInt(atAddress:)
时使用隐式桥接将指针传递给 numbers
的元素。
let numbers = [5, 10, 15, 20]
printInt(atAddress: numbers)
// Prints "5"
您还可以使用 inout 语法将可变指针传递给数组的元素。因为printInt(atAddress:)
需要一个不可变指针,虽然这在语法上是有效的,但它不是必需的。
var mutableNumbers = numbers
printInt(atAddress: &mutableNumbers)
无论你以哪种方式调用 printInt(atAddress:)
,Swift 的类型安全保证你只能传递一个指向函数所需类型的指针——在本例中,是一个指向 Int
的指针。
可用版本
相关用法
- Swift UnsafePointer ...(_:)用法及代码示例
- Swift UnsafePointer ..<(_:)用法及代码示例
- Swift UnsafePointer ...(_:_:)用法及代码示例
- Swift UnsafePointer withMemoryRebound(to:capacity:_:)用法及代码示例
- Swift UnsafePointer ..<(_:_:)用法及代码示例
- Swift UnsafeMutableRawPointer ..<(_:_:)用法及代码示例
- Swift UnsafeBufferPointer randomElement()用法及代码示例
- Swift UnsafeRawBufferPointer.Iterator dropFirst(_:)用法及代码示例
- Swift UnsafeMutablePointer allocate(capacity:)用法及代码示例
- Swift UnsafeRawBufferPointer.Iterator max()用法及代码示例
- Swift UnsafeBufferPointer min(by:)用法及代码示例
- Swift UnsafeMutableBufferPointer allocate(capacity:)用法及代码示例
- Swift UnsafeRawBufferPointer shuffled(using:)用法及代码示例
- Swift UnsafeBufferPointer prefix(upTo:)用法及代码示例
- Swift UnsafeMutableRawPointer ...(_:_:)用法及代码示例
- Swift UnsafeMutableBufferPointer prefix(through:)用法及代码示例
- Swift UnsafeRawBufferPointer isEmpty用法及代码示例
- Swift UnsafeMutableRawBufferPointer shuffle()用法及代码示例
- Swift UnsafeRawPointer advanced(by:)用法及代码示例
- Swift UnsafeRawBufferPointer enumerated()用法及代码示例
- Swift UnsafeBufferPointer firstIndex(of:)用法及代码示例
- Swift UnsafeMutableBufferPointer map(_:)用法及代码示例
- Swift UnsafeMutablePointer withMemoryRebound(to:capacity:_:)用法及代码示例
- Swift UnsafeRawBufferPointer subscript(_:)用法及代码示例
- Swift UnsafeBufferPointer map(_:)用法及代码示例
注:本文由纯净天空筛选整理自apple.com大神的英文原创作品 UnsafePointer。非经特殊声明,原始代码版权归原作者所有,本译文未经允许或授权,请勿转载或复制。