Swift 取得變數的 Pointer/Address
==
# 工具
* `withUnsafePointer(to:)` [Doc](https://developer.apple.com/documentation/swift/2431879-withunsafepointer)
> `func withUnsafePointer<T, Result>(to value: inout T, _ body: (UnsafePointer<T>) throws -> Result) rethrows -> Result`
>
* `withUnsafePointer(to:_:)` [Doc](https://developer.apple.com/documentation/swift/2429788-withunsafemutablepointer)
> `func withUnsafeMutablePointer<T, Result>(to value: inout T, _ body: (UnsafeMutablePointer<T>) throws -> Result) rethrows -> Result`
* `Array<T>::withUnsafeBufferPointer(_:)` [Doc](https://developer.apple.com/documentation/swift/array/2994771-withunsafebufferpointer)
> `func withUnsafeBufferPointer<R>(_ body: (UnsafeBufferPointer<Element>) throws -> R) rethrows -> R`
* Swift Compiler's implicit bridge for Array
# Single Variable
* `withUnsafeMutablePointer` has `inout` in first parameter, it need leading `&` when passing
```
var x = 1
withUnsafePointer(to: x) { ptr in
print(type(of: ptr))
print(ptr.pointee)
}
withUnsafeMutablePointer(to: &x) { ptr in
print(type(of: ptr))
print(ptr.pointee)
}
func seeAddr<T>(_ ptr: UnsafePointer<T>) {
print(type(of: ptr))
print(ptr.pointee)
}
seeAddr(&x)
```
## Output
```
UnsafePointer<Int>
1
UnsafeMutablePointer<Int>
1
UnsafePointer<Int>
1
```
# Array
> * need use inout syntax(&) for `withUnsafeMutablePointer`
> * `withUnsafePointer` is used to get `Array<T>` instead of `T` in `Array`
> * To extract `T` from `Array<T>`, need to use `Array<T>`'s method `withUnsafeBufferPointer`
```
var a = [1,2,3]
// withUnsafePointer(to: T, (UnsafePointer->Result)) -> Result
withUnsafePointer(to: a) { ptr in
print(type(of: ptr))
}
// withUnsafeMutablePointer(to: inout T, (UnsafeMutablePointer->Result)) -> Result
withUnsafeMutablePointer(to: &a) { ptr in
print(type(of: ptr))
}
// Array<T>::withUnsafeBufferPointer((UnsafeBufferPointer->Result)) -> Result
a.withUnsafeBufferPointer { ptr in
print(type(of: ptr))
}
```
## Output
```
UnsafePointer<Array<Int>>
UnsafeMutablePointer<Array<Int>>
UnsafeBufferPointer<Int>
```
# Get address as `UnsafePointer<T>` from Array
> `withUnsafePointer` seems is unable to get correct address
```
var a = [2,3,5]
withUnsafePointer(to: a[0]) { ptr in
print(type(of: ptr))
print(ptr[0]) // print 1
print(ptr[1]) // still print 1, it seems ptr does not point to the original one
}
withUnsafeMutablePointer(to: &a[0]) { ptr in
print(type(of: ptr))
print(ptr[0])
print(ptr[1])
print(ptr[2])
}
a.withUnsafeBufferPointer{ ptr in
print(type(of: ptr))
print(ptr[0])
print(ptr[1])
print(ptr[2])
let addrOpt = ptr.baseAddress
print(type(of: addrOpt))
let addr = addrOpt!
print(type(of: addr))
print(addr[0])
print(addr[1])
print(addr[2])
}
```
## Output
```
UnsafePointer<Int>
2
2
UnsafeMutablePointer<Int>
2
3
5
UnsafeBufferPointer<Int>
2
3
5
Optional<UnsafePointer<Int>>
UnsafePointer<Int>
2
3
5
```
# Implicit Bridge Array to `UnsafePointer<T>` when passing as function parameter
::: warning
According to https://developer.apple.com/documentation/swift/unsafepointer
> The pointer created through implicit bridging of an instance or of an array’s elements is only valid during the execution of the called function. Escaping the pointer to use after the execution of the function is undefined behavior. In particular, do not use implicit bridging when calling an UnsafePointer initializer.
```
var number = 5
let numberPointer = UnsafePointer<Int>(&number)
// Accessing 'numberPointer' is undefined behavior.
```
:::
```
var a = [2,3,5]
func seeAddr<T>(_ ptr: UnsafePointer<T>) {
print(ptr[0])
print(ptr[1])
print(ptr[2])
}
print("implicit bridge Array to UnsafePointer<T>")
seeAddr(a) // implicit bridge Array<T> to UnsafePointer<T>
print("implicit bridge Array with inout syntax(&) to UnsafePointer<T>")
seeAddr(&a) // implicit bridge Array<T> with inout syntax to UnsafePointer<T>
```
## Output
```
implicit bridge Array to UnsafePointer<T>
2
3
5
implicit bridge Array with inout syntax(&) to UnsafePointer<T>
2
3
5
```
# Reference
* [UnsafePointer](https://developer.apple.com/documentation/swift/unsafepointer)