26

I'm trying to gain a deeper understanding of how Swift copies value types:

The behavior you see in your code will always be as if a copy took place. However, Swift only performs an actual copy behind the scenes when it is absolutely necessary to do so.

To advance my understanding, I'd like to get the memory address of a value type. I tried unsafeAddressOf(), but this doesn't work with structs and it seems to cast Swift's standard library types to reference types (e.g. String is cast to NSString).

How can I get the memory address of a value type, like an instance of Int, or a custom struct in Swift?

3 Answers 3

38

According to Martin R' s answer

addressOf() cannot be used with struct variables. String is a struct, however, it is automatically bridged to NSString when passed to a function expecting an object.

According to nschum's answer, you can get the (stack) address of a struct, build-in type or object reference like this:

import UIKit


func address(o: UnsafePointer<Void>) -> Int {
    return unsafeBitCast(o, Int.self)
}

func addressHeap<T: AnyObject>(o: T) -> Int {
    return unsafeBitCast(o, Int.self)
}


struct myStruct {
    var a: Int
}

class myClas {

}
//struct
var struct1 = myStruct(a: 5)
var struct2 = struct1
print(NSString(format: "%p", address(&struct1))) // -> "0x10f1fd430\n"
print(NSString(format: "%p", address(&struct2))) // -> "0x10f1fd438\n"

//String
var s = "A String"
var aa = s
print(NSString(format: "%p", address(&s))) // -> "0x10f43a430\n"
print(NSString(format: "%p", address(&aa))) // -> "0x10f43a448\n"

//Class
var class1 = myClas()
var class2 = class1
print(NSString(format: "%p", addressHeap(class1))) // -> 0x7fd5c8700970
print(NSString(format: "%p", addressHeap(class2))) // -> 0x7fd5c8700970

unsafeAddressOf(class1) //"UnsafePointer(0x7FD95AE272E0)"
unsafeAddressOf(class2) //"UnsafePointer(0x7FD95AE272E0)"

//Int
var num1 = 55
var num2 = num1
print(NSString(format: "%p", address(&num1))) // -> "0x10f1fd480\n"
print(NSString(format: "%p", address(&num2))) // -> "0x10f1fd488\n"

One thing I found is, if myStruct has no value, the address will be retain same:

struct myStruct {

}

var struct1 = myStruct()
var struct2 = struct1
print(NSString(format: "%p", address(&struct1))) // -> ""0xa000000000070252\n""
print(NSString(format: "%p", address(&struct2))) // -> ""0xa000000000070252\n""
Sign up to request clarification or add additional context in comments.

6 Comments

So this proves that Swift doesn't implement copy-on-write optimization for custom Structs, only for a few built in types and Classes. Interesting.
@karansatia Classes are reference types, so they are not copied upon assignment. If you assign a class instance to another object, they will point to the same object. Therefore it is normal that in the example above we have the same address for both classes. It has nothing to do with the copy-on-write. This is true whether or not they are built-in or custom classes. You must implement NSCopying to make your class cloneable, and assign it this way: b = a.copy() as? MyClass rather then b = a
The Swift 5 version of the address function: func address(o: UnsafeRawPointer) -> Int { return Int(bitPattern: o) }
How to do the same if let struct1 = myStruct() my struct is let not var?
Is this answer correct? It looks like what I printed out is the pointer address, not the address of the struct.. From this code: gist.github.com/luoshuaiqing/dc4a1d45b051025b2c2a35fc5c87f6a7, the class doesn't even have the same address (which is incorrect if this address is of the object)
|
16

I'm not sure if there's a "recommended" way to do that, but one method is to use withUnsafePointer(_:_:), like this:

var s: String = "foo"
withUnsafePointer(to: &s) { print("\($0)") }

This printed 0x00007ffff52a011c8 on my machine.

2 Comments

Swift 4.2: withUnsafePointer(to: &s, { NSLog("($0)") })
@jreft56 you are correct, its the same with Swift 5.2
16

Swift 2.0 :

You can use this unsafeAddressOf(someObject)

or in Swift 3.0:

use withUnsafePointer(to: someObject) { print("\($0)") }

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.