A pointer for accessing data of a specific type.
SDK
- Xcode 6.0.1+
Framework
- Swift Standard Library
Declaration
Overview
You use instances of the Unsafe
type to access data of a specific type in memory. The type of data that a pointer can access is the pointer’s Pointee
type. Unsafe
provides no automated memory management or alignment guarantees. You are responsible for handling the life cycle of any memory you work with through unsafe pointers to avoid leaks or undefined behavior.
Memory that you manually manage can be either untyped or bound to a specific type. You use the Unsafe
type to access and manage memory that has been bound to a specific type.
Understanding a Pointer’s Memory State
The memory referenced by an Unsafe
instance can be in one of several states. Many pointer operations must only be applied to pointers with memory in a specific state—you must keep track of the state of the memory you are working with and understand the changes to that state that different operations perform. 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. In the following example, ptr
is a pointer to memory initialized with a value of 23
:
Accessing a Pointer’s Memory as a Different Type
When you access memory through an Unsafe
instance, the Pointee
type must be consistent with the bound type of the memory. If you do need to access memory that is bound to one type as a different type, Swift’s pointer types provide type-safe ways to temporarily or permanently change the bound type of the memory, or to load typed instances directly from raw memory.
An Unsafe
instance allocated with eight bytes of memory, uint8Pointer
, will be used for the examples below.
When you only need to temporarily access a pointer’s memory as a different type, use the with
method. For example, you can use this method to call an API that expects a pointer to a different type that is layout compatible with your pointer’s Pointee
. The following code temporarily rebinds the memory that uint8Pointer
references from UInt8
to Int8
to call the imported C strlen
function.
When you need to permanently rebind memory to a different type, first obtain a raw pointer to the memory and then call the bind
method on the raw pointer. The following example binds the memory referenced by uint8Pointer
to one instance of the UInt64
type:
After rebinding the memory referenced by uint8Pointer
to UInt64
, accessing that pointer’s referenced memory as a UInt8
instance is undefined.
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. Convert your pointer to an Unsafe
instance and then use the raw pointer’s load(from
method to read values.
Performing Typed Pointer Arithmetic
Pointer arithmetic with a typed pointer is counted in strides of the pointer’s Pointee
type. When you add to or subtract from an Unsafe
instance, the result is a new pointer of the same type, offset by that number of instances of the Pointee
type.
You can also use subscript notation to access the value in memory at a specific offset.
Implicit Casting and Bridging
When calling a function or method with an Unsafe
parameter, you can pass an instance of that specific pointer type, pass an instance of a compatible pointer type, or use Swift’s implicit bridging to pass a compatible pointer.
For example, the print
function in the following code sample expects an Unsafe
instance as its first parameter:
As is typical in Swift, you can call the print
function with an Unsafe
instance. This example passes int
, a pointer to an Int
value, to print(address:)
.
Because a mutable typed pointer can be implicitly cast to an immutable pointer with the same Pointee
type when passed as a parameter, you can also call print
with an Unsafe
instance.
Alternatively, you can use Swift’s implicit bridging to pass a pointer to an instance or to the elements of an array. The following example passes a pointer to the value
variable by using inout syntax:
An immutable pointer to the elements of an array is implicitly created when you pass the array as an argument. This example uses implicit bridging to pass a pointer to the elements of numbers
when calling print
.
You can also use inout syntax to pass a mutable pointer to the elements of an array. Because print
requires an immutable pointer, although this is syntactically valid, it isn’t necessary.
No matter which way you call print
, Swift’s type safety guarantees that you can only pass a pointer to the type required by the function—in this case, a pointer to an Int
.
Important
The pointer created through implicit bridging of an instance or of an array’s elements is only valid during the execution of the called function. Escaping the pointer to use after the execution of the function is undefined behavior. In particular, do not use implicit bridging when calling an Unsafe
initializer.