Are pointers always set to nil on declaration?
Under ARC, all object pointers are set to nil
upon initialization. When not running under ARC, or when using pointers to other datatypes, an uninitialized pointer will have a garbage value (and in fact reading from the pointer produces undefined behavior according to the C standard).
@Chuck points out something important, which is that this only applies to local variables. Any variable with static storage (function statics, or globals) and instance variables are always initialized to their respective zero value (which, for pointers, is nil
/NULL
).
(For ARC, see Lily Ballard's answer)
Can/should I rely on this?
Nope - never rely on that. Stack memory is typically zeroed in debug builds (depends on your compiler settings). With optimization enabled, the compiler does not do that for you and you'll be given garbage values based on whatever happened to exist on the stack region last.
You can rely on zeroed ivars in your objects' initializers.
You can guard yourself from this with the static analyzer, and by enabling -Wuninitialized
for your build configs when the optimization level is greater than -O0
.
A corollary question: what is the correct terminology to describe foo in the state at the end of the lines marked 1, 2 and 3? I imagine at least one of 1 & 2 them is termed 'uninitialised', and one of 2 & 3 is 'initialised', but which, and what do we call the third option?
- Uninitialized
- An objc instance which has been allocated, but has not been initialized (not safe to use otherwise)
- An initialized objc instance or object.
An answer to your corollary question:
After #1, foo has been declared but is uninitialized.
After #2, foo has been allocated but is still uninitialized.
After #3, foo has been initialized.
In practice, you never want to separate steps 2 and 3, that is your code should be foo = [[NSString alloc] init]
. The reason for this is that it is "dangerous" to allocate an object and not initialize it, or to initialize it improperly.
If you just do this foo = [NSString alloc]
but forget to ever call init, it is not safe to use foo since it hasn't been initialized. Likewise, it is equally unsafe to do this [foo init]
(notice the lack of reassignment to foo) because init can return a different reference to the initialized object than was originally allocated by alloc.