Home swift-unsafe pointer
Post
Cancel

swift-unsafe pointer

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
This post is licensed under CC BY 4.0 by the author.