Consider I have a struct Person with a property "name". Why changing the name property results in a new memory address?
struct Person {
var name = "Alex"
}
var person = Person()
withUnsafePointer(to: person) { print($0)
} // 0x000000016fdff248
person.name = "John"
withUnsafePointer(to: person) { print($0)
} // 0x000000016fdff208
CodePudding user response:
You're calling the wrong version of withUnsafePointer(to:)
. If you call the right one, it behaves as you expect (though it is not promised to do so). The one you're calling is:
func withUnsafePointer<T, Result>(to value: T, _ body: (UnsafePointer<T>) throws -> Result) rethrows -> Result
That passes a copy of value
to the function. It doesn't even require that there be memory allocated; it'll allocate memory itself to ensure that there's something to point to:
// Who needs a variable?
withUnsafePointer(to: 4) { print($0) } // 0x000000016fdff348
withUnsafePointer(to: 4) { print($0) } // 0x000000016fdff340
But there's also an inout
version of this function, and I expect it's what you really meant to call:
func withUnsafePointer<T, Result>(to value: inout T, _ body: (UnsafePointer<T>) throws -> Result) rethrows -> Result
That expects a reference to the value. Note the use of &
here, and that it behaves as you're expecting:
var person = Person()
withUnsafePointer(to: &person) { print($0) } // 0x0000000100008018
person.name = "John"
withUnsafePointer(to: &person) { print($0) } // 0x0000000100008018
Do not read too much into this. The compiler does not promise stable addresses except in very specific cases as MartinR noted. There is no safe way to hold onto a pointer to a struct (and references are not quite the same thing as pointers in any case). Structs are not even promised to allocate memory. Every Int is a struct, after all. But if you use the inout
version of this call, I think the mystery disappears.