This article is the 12th day article of Swift Advent Calendar 2014.
The Advent Calendar is just around the corner. December is already the 12th, which makes you feel the end of the year.
Personally, as I get older, I feel that the year is very early. The ancestor also left the words ** "The number of days experienced in a year is the reciprocal of age" **. (Let's not make a mistake that the value does not change so much even if the reciprocal of 1 or more is taken)
Now let's move on to the topic of Swift.
The language design for Swift is good, but the support for Xcode and the compiler are still so high that I've never been motivated to make an app by myself. (If you optimize a certain code, it may loop infinitely)
This time, it's not about the compiler, but about accessing memory directly using pointers.
First, Swift has a C-compatible API.
For example, while creating an iOS or Mac application
var error: NSError? = nil
if !_fetchedResultsController!.performFetch(&error) {
println("Unresolved error \(error), \(error?.localizedDescription)")
}
return _fetchedResultsController!
You should remember writing. (Located in the project's Core Data template)
The address of the variable declared in this NSError?
Is passed to the argument of performFetch
.
If you go to see the definition of performFetch
func performFetch(error: NSErrorPointer) -> Bool
And NSErrorPointer
is aliased as below.
typealias NSErrorPointer = AutoreleasingUnsafeMutablePointer<NSError?>
The ʻAutoreleasingUnsafeMutablePointer
By nature, Swift does not have direct access to memory.
However, it is possible by using ʻUnsafePointer
I mentioned ʻUnsafe Pointer
For return types, variables, and arguments, the following mappings apply:
C Syntax | Swift Syntax |
---|---|
const Type * |
UnsafePointer<Type> |
Type * |
UnsafeMutablePointer<Type> |
For class types, the following mappings apply:
C Syntax | Swift Syntax |
---|---|
Type * const * |
UnsafePointer<Type> |
Type * __strong * |
UnsafeMutablePointer<Type> |
Type ** |
AutoreleasingUnsafeMutablePointer<Type> |
As mentioned above, the pointer types are
It is divided into.
as a feature
--Use nil
in Swift to represent NULL
in C
--Converted to ʻUnsafePointer
Let's actually use these.
This time, as an example of a pointer, I will introduce a swapByPointer function. (The swap function appears frequently in the pointer example.)
I want the type to be any type, so I use generics.
** swapByPointer function **
func swapByPointer<T>(x: UnsafeMutablePointer<T>, y: UnsafeMutablePointer<T>) {
let z: T = x.memory
x.memory = y.memory
y.memory = z
}
call
var a: Int = 10
var b: Int = 20
// a = 10, b = 20
println("a = \(a), b = \(b)")
// Swap
swapByPointer(&a, &b)
// a = 20, b = 10
println("a = \(a), b = \(b)")
It looks like this.
I define a normal swap function and pass the address as its argument. We are assigning directly to the memory pointed to by the address in the function.
I think there is a tsukkomi of "No, isn't it simpler to use such ʻinout`?"
This time I want to use ** pointer ** explicitly, so I don't use ʻinout`.
If you are asking "What is ʻinout`?", Please read the code below.
** swapByInout function (inout version) **
func swapByInout<T>(inout x: T, inout y: T) {
let z: T = x
x = y
y = z
}
call
var a: Int = 10
var b: Int = 20
// a = 10, b = 20
println("a = \(a), b = \(b)")
// Swap
swapByInout(&a, &b)
// a = 20, b = 10
println("a = \(a), b = \(b)")
The previous reference was from the address of the variable already allocated, but if you are familiar with C language, it will be "** memory alloc ** !?".
Of course there is.
alloc
// Use UnsafeMutablePointer<T>
typealias IntPointer = UnsafeMutablePointer<Int>
// C Language:
// typedef int *IntPointer;
var a_ptr = IntPointer.alloc(1)
// C Language:
// int *a_ptr = (int *)malloc(1 * sizeof(int));
// IntPointer a_ptr = (IntPointer)malloc(1 * sizeof(int));
// or
// int *a_ptr = (int *)calloc(1, sizeof(int));
var b_ptr = IntPointer.alloc(1)
a_ptr.memory = a
// C Language:
// *a_ptr = a;
b_ptr.memory = b
// a_ptr.memory = 10, b_ptr.memory = 20
println("a_ptr.memory = \(a_ptr.memory), b_ptr.memory = \(b_ptr.memory)")
// Swap
swapByPointer(a_ptr, b_ptr)
// a_ptr.memory = 20, b_ptr.memory = 10
println("a_ptr.memory = \(a_ptr.memory), b_ptr.memory = \(b_ptr.memory)")
// Destroy
a_ptr.dealloc(1)
// C Language:
// free(a_ptr);
b_ptr.dealloc(1)
As a comment, I also wrote down the situation in C language.
There are three codes that need explanation: ʻalloc,
dealloc, and
memory`.
var p = UnsafeMutablePointer
In C language
Type *p = (Type *)malloc(num * sizeof(Type));
// or
Type *p = (Type *)calloc(num, sizeof(Type));
It will be.
Specify the number of declared types in num
to secure the required memory size.
p.dealloc(num)
In C language
free(p);
I'm releasing it.
p.memory
In C language
*p
is. Used to refer to the value in the address.
Generally, if you know this degree, you can build Swift with the idea of C language.
I have given this code to Gist, so please refer to it if you like.
https://gist.github.com/kaneshin/564fc0780e0d1c9cac7d
Also, if you talk about pointers, you should be asked ** "What is a function pointer?" **.
Of course, there is also a compatible API for working with function pointers. Let's say that someone wants to know, or will introduce it when the ** stock number of this article reaches about 100 **.
It was such a great deal, but I don't think there is an article in Japanese dealing with pointers in Swift, so please touch it if you like.
Recommended Posts