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。非經特殊聲明,原始代碼版權歸原作者所有,本譯文未經允許或授權,請勿轉載或複製。