Static Variables In Functions
Welcome back to Objective-C Tuesdays after a long hiatus. Picking up
from where we left
off, today we'll look at static
variables declared at
function scope.
Normal local variables are declared inside the body of a function:
int countCharInString(char c, char const *s) {
int count = 0; // plain old local variable
do {
if (*s == c) ++count;
} while (*s++);
return count;
// after we return, count ceases to exist
}
Plain old local variables exist only for the time that the function is
executing. When the function returns, local variables vanish.
Sometimes you want to keep a value around between calls to a function.
Typically you use a global variable for this, but if the variable is
only ever used inside a single function, you can use a
static
variable declared inside the function instead. One
common use for this is to automatically initialize a singleton object
or data structure before its first use. For example:
// static variable declared in a function
NSArray *getDaysOfTheWeek() {
static NSArray *daysOfTheWeek = nil;
if ( ! daysOfTheWeek) {
daysOfTheWeek = [[NSArray alloc] initWithObjects:@"Sunday",
@"Monday", @"Tuesday", @"Wednesday",
@"Thursday", @"Friday", @"Saturday", nil];
}
return daysOfTheWeek;
}
The static
variable daysOfTheWeek
is actually
a global variable and follows the same rules as global variables with
one difference: it's only visible inside the
getDaysOfTheWeek()
function. This makes it seem like some
magical kind of local variable that keeps its value between function
calls, but in fact, you can rewrite getDaysOfTheWeek()
to
use a normal static
global like this:
// same function using a static global variable instead
static NSArray *daysOfTheWeek = nil;
NSArray *getDaysOfTheWeek() {
if ( ! daysOfTheWeek) {
daysOfTheWeek = [[NSArray alloc] initWithObjects:@"Sunday",
@"Monday", @"Tuesday", @"Wednesday",
@"Thursday", @"Friday", @"Saturday", nil];
}
return daysOfTheWeek;
}
There are only a couple of minor advantages to using a
static
variable declared in a function rather than a
normal global:
-
the
static
variable lives near the code that uses it
-
global variable name clashes are avoided
However, because it's a global variable, it suffers from all the
problems that global variables do. Code that make extensive use of
global variables is often harder to understand and difficult to reuse.
In a multithreaded application, global variables need to be carefully
synchronized between threads to avoid data corruption and deadlocks.
Global variables also make writing automated tests more difficult and
sometimes even impossible. In general, it's best to avoid using global
variables.
Next time, we'll take a look at
local
variables and function parameters.