UnsafePointer
@frozon
struct
UnsafePointer
A pointer for accessing data of a specific type.
memory state
Memory can be untyped and uninitialized
, bound to a type and uninitialized
, or bound to a type and initialized to a value
. Finally, memory that was allocated previously may have been deallocated
, leaving existing pointers referencing unallocated memory.
Uninitialized Memory
Memory that has just been allocated through a typed pointer or has been deinitialized is in an uninitialized state. Uninitialized memory must be initialized before it can be accessed for reading.
Initialized Memory
Initialized memory has a value that can be read using a pointer’s pointee
property or through subscript notation.
1
2
3
let ptr: UnsafePointer<Int> = ...
// ptr.pointee == 23
// ptr[0] == 23
Accessing a Pointer’s Memory as a Different Type
When you only need to temporarily access a pointer’s memory as a different type, use the withMemoryRebound(to:capacity:)
method.
1
let uint8Pointer: UnsafePointer<UInt8> = fetchEightBytes()
1
2
3
4
5
6
7
// Imported from C
func strlen(_ __s: UnsafePointer<Int8>!) -> UInt
let length = uint8Pointer.withMemoryRebound(to: Int8.self, capacity: 8) {
return strlen($0)
}
// length == 7
When you need to permanently rebind memory to a different type, first obtain a raw pointer to the memory and then call the bindMemory(to:capacity:)
method on the raw pointer.
1
2
let uint64Pointer = UnsafeRawPointer(uint8Pointer)
.bindMemory(to: UInt64.self, capacity: 1)
Alternatively, you can access the same memory as a different type without rebinding through untyped memory access, so long as the bound type and the destination type are trivial types.
1
2
3
let rawPointer = UnsafeRawPointer(uint64Pointer)
let fullInteger = rawPointer.load(as: UInt64.self) // OK
let firstByte = rawPointer.load(as: UInt8.self) // OK
Performing Typed Pointer Arithmetic
1
2
3
4
5
6
7
8
9
10
11
// '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