Pointers in Swift

emacos picture emacos · Feb 22, 2017 · Viewed 10.7k times · Source

I'm trying to understand the use of pointers in Swift, in particular: Unsafe[Mutable]Pointer and UnsafeRaw[Mutable]Pointer. I have several questions on the subject.

  1. Is UnsafePointer <T> equal to const T * Pointer in ? and UnsafeMutablePointer <T> is equal to T * Pointer in C?

  2. What is the difference between Unsafe[Mutable]Pointer and UnsafeRaw[Mutable]Pointer?

  3. Why does this compile

func receive(pointer: UnsafePointer<Int> ) {
    print("param value is: \(pointer.pointee)")
}

var a: Int = 1
receive(pointer: &a) // prints 1

but this gives me an error?

var a: Int = 1
var pointer: UnsafePointer<Int> = &a // error : Cannot pass immutable value of type 'Int' as inout argument

Answer

JAL picture JAL · Feb 22, 2017
  1. Is UnsafePointer <T> equal to const T * Pointer in ? and UnsafeMutablePointer <T> is equal to T * Pointer in C?

Well, use a bridging header in a Swift app to see how the C pointers are bridged:

const int *myInt;
int *myOtherInt;

bridges to

var myInt: UnsafePointer<Int32>!
var myOtherInt: UnsafeMutablePointer<Int32>!
  1. What is the difference between Unsafe[Mutable]Pointer and UnsafeRaw[Mutable]Pointer?

Swift 3 added a UnsafeRawPointer API to replace the Unsafe[Mutable]Pointer<Void> type. Conversion between pointers of a different type is no longer allowed in Swift. Instead, the API provides interfaces (.assumingMemoryBound(to:) or .bindMemory(to:capacity:)) to bind memory to a type.

With regard to question 3, the ampersand means that the variable is inout. I don't believe you can declare a variable as inout unless it is being used by a function that directly modifies the underlying memory, but I'll let the experts correct me. Instead, use withUnsafePointer.

Thanks to Martin's helpful comment, this syntax was never valid in Swift, and there is no safe way to create "free pointers" to Swift variables.