1

Let's say I do the following in C++:

int i = 1;
int* ptr = &i;
*ptr = 2;
cout << i << '\n'; 

And I want to do something similar in swift. Could I do the following?

var i : Int = 1
var iptr : UnsafeMutablePointer<Int> = &i
iptr.memory = 2
print(i)

And achieve the same result?

0

2 Answers 2

3

Yes-ish.

You can't do it exactly as you've attempted in the question. It won't compile. Swift won't let you directly access the address of a value like this. At the end of the day, the reason is mostly because there's simply no good reason to do so.

We do see the & operator in Swift however.


First of all, there is the inout keyword when declaring function parameters:

func doubleIfPositive(inout value: Float) -> Bool {
    if value > 0 {
        value *= 2
        return true
    }
    return false
}

And to call this method, we'd need the & operator:

let weMadeARadian = doubleIfPositive(&pi)

We can see it similarly used when we have a function which takes an argument of type UnsafeMutablePointer (and other variants of these pointer structs). In this specific case, it's primarily for interoperability with C & Objective-C, where we could declare a method as such:

bool doubleIfPositive(float * value) -> bool {
    if (value > 0) {
        value *= 2;
        return true;
    }
    return false;
}

The Swift interface for that method ends up looking somethin like this:

func doubleIfPositive(value: UnsafeMutablePointer<Float>) -> Bool

And calling this method from Swift actually looks just like it did before when using the inout approach:

let weMadeARadian = doubleIfPositive(&pi)

But these are the only two uses of this & operator I can find in Swift.

With that said, we can write a function that makes use of the second form of passing an argument into a method with the & operator and returns that variable wrapped in an unsafe mutable pointer. It looks like this:

func addressOf<T>(value: UnsafeMutablePointer<T>) -> UnsafeMutablePointer<T> {
    return value
}

And it behaves about as you'd expect from your original code snippet:

var i: Int = 1
var iPtr = addressOf(&i)
iPtr.memory = 2
print(i) // prints 2

enter image description here


As noted by Kevin in the comments, we can also directly allocate memory if we want.

var iPtr = UnsafeMutablePointer<Int>.alloc(1)

The argument 1 here is effectively the mount of space to allocate. This says we want to allocate enough memory for a single Int.

This is roughly equivalent to the following C code:

int * iPtr = malloc(1 * sizeof(int));

enter image description here


BUT...

If you're doing any of this for anything other than interoperability with C or Objective-C, you're most likely not Swifting correctly. So before you start running around town with pointers to value types in Swift, please, make sure it's what you absolutely need to be doing. I've been writing Swift since release, and I've never found the need for any of these shenanigans.

Sign up to request clarification or add additional context in comments.

8 Comments

Great answer, scrapping mine but there is one thing to add. You are able to allocate memory yourself and declare a pointer type with var iptr : UnsafeMutablePointer<Int> = UnsafeMutablePointer.alloc(1).
@Kevin Yeah, I can add that to the answer. It's useful information (and helps make this more canonical), but that's a bit different from what the question is asking.
Are you sure caling addressOf with the & operator addressOf(&i) is safe? From Apple's Interacting with C APIs: "The pointer passed to the function is guaranteed to be valid only for the duration of the function call. Don’t try to persist the pointer and access it after the function has returned." — addressOf violates that. Apple specifically speaks about UnsafePointer, but the same should apply to UnsafeMutablePointer, right?
Nope (I'm not sure it's safe). See the disclaimer at the bottom of the answer. I'd absolutely not recommend doing any of this, really. The memory management rules end up being completely different here and really, something else could deallocate that memory out from under us and use it for something else. Again, if you're doing any of this, you're almost certainly Swifting wrong.
I saw your disclaimer, but I think it's important to point out that the addressOf example is not allowed in Swift (I think) while your other examples are perfectly valid.
|
3

Like this (not the only way, but it's clear):

var i : Int = 1
withUnsafeMutablePointer(&i) {
    iptr -> () in
    iptr.memory = 2
}
print(i)

Not a very interesting example, but it is completely parallel to your pseudo-code, and we really did reach right into the already allocated memory and alter it, which is what you wanted to do.

This sort of thing gets a lot more interesting when what you want to do is something like cycle thru memory just as fast as doing pointer arithmetic in C.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.