See Also
Variables in Objective-C
Welcome back and happy new year! Last time we looked at global variables and their initialization. Today we'll look at how to share global variables between Variables in Objective-C
.c
and .m
code files.Frequently, you define a global variable in one code file and use it in another. For instance, the file
MyView.m
might contain the global variable doubleTapEnabled
:// MyView.m #include <Foundation/Foundation.h> // ... BOOL doubleTapEnabled = YES; // ...To use this variable in
main.m
you might do this:// main.m #include <Foundation/Foundation.h> BOOL doubleTapEnabled; int main(void) { // ... NSLog(@"doubleTapEnabled = %i", doubleTapEnabled); // ... }This will work the way you expect, but there's a subtle potential gotcha here. Notice that in
MyView.m
we initialize doubleTapEnabled
to YES
. When the compiler sees that, it interprets that statement as a global variable definition and allocates space for the doubleTapEnabled
variable and sets its initial value. However, in
main.m
we don't give doubleTapEnabled
an initial value, which makes that statement ambiguous: it could be a global variable declaration for doubleTapEnabled
or a definition, with doubleTapEnabled
initialized to zero (NO
).The difference between a declaration and a definition can be confusing since they're closely related (and the two words are unfortunately very similar). A declaration tells the compiler that a global variable, struct, class or function exists somewhere. A definition gives the compiler all the information it needs to generate the code for a global variable, struct, class or function.
A statement like
BOOL doubleTapEnabled;can be either a declaration or a definition. At link time, if an unambiguous definition isn't found, the global variable will be created and initialized to zero; if an unambiguous definition is found, that definition will be used to create the global variable.
So if you do something like this:
// ERROR: won't link // MyView.m // ... BOOL doubleTapEnabled = YES; // unambiguous definition // ... // main.m // ... BOOL doubleTapEnabled = YES; // unambiguous definition // ...You will get a linker error like "duplicate symbol _doubleTapEnabled" because you told the compiler to create the same global variable in two different places.
This is where the
extern
keyword comes in. You use extern
with global variables to create unambiguous declarations. In addition to helping the compiler, it also clues in anyone reading the code that the global variable is defined (and possibly initialized) elsewhere, but you're simply using it here. So we can rewrite our example like this:// MyView.m // ... BOOL doubleTapEnabled = YES; // unambiguous definition // ... // main.m // ... extern BOOL doubleTapEnabled; // defined in MyView.m // ...And now
doubleTapEnabled
is happily unambiguous everywhere.It's common style to add
extern
to all global variable declarations in your header (.h
) files and provide a corresponding definition in a source (.m
or .c
) file. So the header file MyView.h
would look like:// MyView.h // ... extern BOOL doubleTapEnabled; // ...The source file
MyView.m
is the same:// MyView.m // ... BOOL doubleTapEnabled = YES; // unambiguous definition // ...And
main.m
now looks like:// main.m // ... #include "MyView.h" // ...Next time, we'll look at using the
static
keyword to make to make a global variable "private" to a source file.
No comments:
Post a Comment