Difficulty: Beginner | Easy | Normal | Challenging
Swift is a memory safe language, but
To access the screenshot above in Xcode you can go through the menu Debug>Debug Workflow>View Memory
and can choose an address to view, as well as the number of bytes.
Prerequisites: Be able to produce a "Hello, World!" iOS application (guide HERE) Understanding of Bit, Bytes and Nibbles
Pointer: An object that stores a memory address UnsafePointer: A pointer for accessing data of a specific type UnsafeRawPointer: A raw pointer for accessing untyped data. This means there is no type safety and no alignment
The image above showing the memory state of my machine (while running an App through Xcode) isn't that easy to see. So we can break it down. The given memory address is 0x112f4a220, and (0 represents octal while x denotes hexadecimal). 0x112f4a220 in Hex is equivalent to the Decimal number 4612989472, and this is the first Denary number on the left hand side of the screen shot. The first row of the screenshot shows the following
Each number (after the memory address) is displayed in Hex. This means that 49, 89, CA and so on is the data at each of these points is 8 bits (Each number can store a maximum of FF in Hex or 255 in Denary) - that is a byte. 4 bytes is a doubleword and (although not clear from the printscreen) the memory is split into these doublewords - to make this clear I've put some red marks on the image:
This gives us the following image of the 24 bits of this particular address:
To help grasp the use of pointers, MemoryLayout is a great enumeration that can describe types in three great ways. Swift has some great functions that allow you to see the size of objects, this is called Memory Layout. There is a full article on Memory Layout HERE, and this works for any type you might use For example a Boolean is 1 byte in size, calculated through the following function:
MemoryLayout<Bool>.size // 1
Although this only makes sense for value types, as a class is a reference type which will return 8 bytes for the size since that is the size of the reference (rather than the pointee that the reference points to).
Pointers are memory addresses, that is a pointer is a variable that holds the memory address of another viable. We might be well-used to the fact that operations in Swift are safe, and the compiler performs static verification (that is Swift is type-safe so we can't assign an Integer to a String without a friendly compiler warning for example). We might want more control, or just want direct control over memory operations. Swift (as ever) helps us out. This is the fundamental difference between Pointer and UnsafePointer, with use of UnsafePointer risking runtime crashes.
There are 8 pointers in swift, separated out into Typed and Raw Pointers. Each of them have an unsafe prefix to make it very obvious that we are managing memory manually.
Why would you need to deal with Pointers? You might need to, when working with C libraries, although you might gain performance increases by using pointers. To start with we cover the UnsafePointer type here in Swift.
A simple Int is placed in memory, and we can view it's location in memory by using withUnsafePointer(to:_:)
var num: Int = 5
withUnsafePointer(to: &num, { ptr in
print (ptr, ptr.pointee)
})
On my particular machine this returns 0x000000011fbde140
, and if you're using my machine you should give it back! If not, however you will probably be given a different memory address. Don't panic, this is expected. The 0x in the returned pointer is of type Hex.
The data is available from pointee and that is the second term (the 5
) that is output from the data.
A similar story is for the String type
var str: String = "A"
withUnsafePointer(to: &str, { ptr in
print (ptr, ptr.pointee)
})
Which in the case of my machine returns 0x000000011ddc91a8 A
An array operates in exactly the same way, and can be accessed with the following code:
var nums: [Int] = [5]
withUnsafePointer(to: &nums, {ptr in
print (ptr, ptr.pointee)
})
Which in the case of my machine returns 0x000000011f630210 [5]
C pointers can be passed in Swift! This is a great strength of Swift, the interoperability with C and Objective C. It isn't the topic at discussion here, so this is example is rather trivial and shows you that passing pointers is possible, further reading will be required if you wish to do this type of coding
var result: CLong = 0
var readersList: UnsafeMutablePointer<CChar>? = nil
var readerLength: CUnsignedLong = 0
result = ListReaders(&readersList, &readerLength)
Ahh, now we're getting to the heart of matters. One thing is that interoperability with C (see the section above). The other reason you might want to deal with pointers is for raw performance. There isn't much more important than performance in some circumstances, so it might be worth making sure you're up to date with this stuff for when you require that performance.
This article serves as a loose introduction into pointers. It shows you how you might want to show locations on the screen, and even how you might want to pass C pointers.
Extend your knowledge Apple have created documentation for MemoryLayout HERE Apple have documentation about Memory Safety HERE The Swift Evolution proposal for MemoryLayout HERE
Subscribing to Medium using this link shares some revenue with me. You might even like to give me a hand by buying me a coffee