0Pricing
Swift Academy · Lesson

UnsafePointer and UnsafeMutablePointer

Read and write raw memory carefully.

UnsafePointer and UnsafeMutablePointer is a free Swift Academy lesson on CoddyKit — lesson 2 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the Swift Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.

Typed Pointers in Swift

Swift's safe references never expose raw addresses, but when interoperating with C or building low-level data structures you reach for typed pointers: UnsafePointer<T> for read-only access and UnsafeMutablePointer<T> for read/write.

A typed pointer knows the element type, so it can compute strides and read a properly-typed value.

// A pointer to an Int we can read but not write
func readFirst(_ p: UnsafePointer<Int>) -> Int {
    return p.pointee
}

The pointee Property

pointee is the value the pointer currently addresses. On a mutable pointer you can both read and assign it; on a read-only pointer you can only read.

Accessing pointee on uninitialized or deallocated memory is undefined behavior — the type system will not catch it.

let p = UnsafeMutablePointer<Int>.allocate(capacity: 1)
p.initialize(to: 42)
print(p.pointee)   // 42
p.pointee = 99
print(p.pointee)   // 99

Allocating Memory

UnsafeMutablePointer<T>.allocate(capacity:) reserves space for capacity elements but does not initialize them. The memory is raw and reading it before initialization is illegal.

// Reserve space for 3 Doubles (uninitialized)
let buffer = UnsafeMutablePointer<Double>.allocate(capacity: 3)
// Must initialize before reading any element

Initialize and Deinitialize

Before reading you must initialize. Before deallocating types that need cleanup (like classes or strings), you must deinitialize to release their resources.

The lifecycle is: allocate → initialize → use → deinitialize → deallocate.

let p = UnsafeMutablePointer<String>.allocate(capacity: 1)
p.initialize(to: "hello")
print(p.pointee)
p.deinitialize(count: 1) // releases the String
p.deallocate()

Always Pair allocate with deallocate

Every allocate must be matched by exactly one deallocate, or you leak memory. Using defer right after allocation is the safest pattern because it runs no matter how the function exits.

func process() {
    let p = UnsafeMutablePointer<Int>.allocate(capacity: 1)
    defer { p.deallocate() }
    p.initialize(to: 7)
    print(p.pointee)
} // deallocate runs here automatically

Pointer Arithmetic

Typed pointers support indexing and arithmetic in element units, not bytes. p + 2 advances by two strides of T. p[i] is shorthand for (p + i).pointee.

let p = UnsafeMutablePointer<Int>.allocate(capacity: 3)
p.initialize(repeating: 0, count: 3)
p[0] = 10
p[1] = 20
p[2] = 30
print((p + 1).pointee) // 20
p.deinitialize(count: 3)
p.deallocate()

Initialize Multiple Elements

For a block of memory, initialize(repeating:count:) sets every slot to the same value, while initialize(from:count:) copies from another buffer. Both fully initialize the range so it is safe to read.

let dst = UnsafeMutablePointer<Int>.allocate(capacity: 4)
dst.initialize(repeating: 5, count: 4)
print(dst[3]) // 5
dst.deinitialize(count: 4)
dst.deallocate()

Read-Only vs Mutable

A function that only inspects data should take UnsafePointer<T>; one that modifies it takes UnsafeMutablePointer<T>. A mutable pointer converts implicitly to a read-only one, but not the reverse — this enforces intent at the API boundary.

func sum(_ p: UnsafePointer<Int>, _ n: Int) -> Int {
    var total = 0
    for i in 0..<n { total += p[i] }
    return total
}
// A mutable pointer can be passed here directly

withUnsafePointer for Locals

To get a temporary pointer to an existing value without allocating, use withUnsafePointer(to:) or its mutable form. The pointer is valid only inside the closure — never let it escape.

var value = 100
withUnsafeMutablePointer(to: &value) { ptr in
    ptr.pointee += 1
}
print(value) // 101

Common Pitfalls

Typed pointers are powerful but unforgiving:

  • Reading pointee before initialize is undefined.
  • Forgetting deinitialize on resource-holding types leaks.
  • Letting a withUnsafePointer pointer escape gives a dangling pointer.

The compiler trusts you here — there are no runtime guard rails.

// DANGEROUS — pointer escapes the closure
// var escaped: UnsafePointer<Int>?
// withUnsafePointer(to: &x) { escaped = $0 }
// escaped!.pointee  // dangling, undefined behavior

A Tiny Manual Stack

Putting it together: allocate a block, treat it as elements with indexing, then clean up. This is the foundation of custom collections and C interop.

let n = 3
let stack = UnsafeMutablePointer<Int>.allocate(capacity: n)
stack.initialize(repeating: 0, count: n)
for i in 0..<n { stack[i] = i * i }
// stack now holds 0, 1, 4
stack.deinitialize(count: n)
stack.deallocate()

Quick Check

Recall the correct pointer lifecycle.

Recap

You now know typed pointers:

  • UnsafePointer reads, UnsafeMutablePointer reads and writes.
  • pointee accesses the value; arithmetic is in element units.
  • The lifecycle is allocate → initialize → use → deinitialize → deallocate, ideally guarded with defer.

Next you will see how buffer pointers wrap a whole contiguous region in a Collection-friendly API.

Frequently asked questions

Is the “UnsafePointer and UnsafeMutablePointer” lesson free?

Yes — the full text of “UnsafePointer and UnsafeMutablePointer” is free to read here on the web, and the Swift Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the Swift Academy course, upgrade to CoddyKit PRO.

What will I learn in “UnsafePointer and UnsafeMutablePointer”?

Read and write raw memory carefully. You practise Swift Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.

Do I need any experience to start Swift Academy?

No prior experience is required. Swift Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 2 of 4, so you can start here or from the beginning and move at your own pace.

How long does the “UnsafePointer and UnsafeMutablePointer” lesson take?

Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.

Can I write and run code in this Swift Academy lesson?

Yes. Every Swift Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.

All lessons in this course

  1. MemoryLayout and Alignment
  2. UnsafePointer and UnsafeMutablePointer
  3. Unsafe Buffer Pointers
  4. withUnsafeBytes and C Interop
← Back to Swift Academy