I am now confused by pointer to pointer even though I\'ve read Why does NSError need double indirection? (pointer to a pointer) and NSError * vs NSError ** and much more.
So, after initialisation on the first line, error
is a pointer to an NSError
object.
In the first log, you are logging the address at which that pointer is held. That's the effect of the & address-of operator. Anyway, that is the address gets passed into the doSomething method.
You're passing in: pointer -> pointer -> nserror-object.
But notice the double indirection in the signature of doSomething. The autoreleasing annotation makes it hard to spot, but its NSError **
.
So the compiler takes your parameter and 'unwraps' it twice.
It starts as pointer -> pointer -> nserror-object. Then after the first indirection it becomes pointer -> nserror-object. Then after the second indirection it becomes nserror-object.
Ergo, you are logging two different things. The first is the address of the pointer to the nserror-object. The second is the address of the nserror-object itself.
EDIT:
@MANIAK_dobrii points out that the object pointed to by error
is itself different in the before and after case.
That's true. If an error occurs in doSomething then it creates an entirely new NSError instance in the else clause. It then loads that back into the error
pointer. That's why you would see two different addresses, afterwards the error
pointer is pointing to another object entirely.
The variable in the caller has type NSError*
. The address has type NSError* *
. The function expect NSError* __autoreleasing *
. Therefore the compiler creates a hidden variable of type NSError* __autoreleasing
, copies the NSError*
into the hidden variable before the call, and copies it back after the call to get the semantics of __autoreleasing right.