2

What the difference between external variable of some sort and static variable?

//ClassA.m
NSString *var1;
static NSString *var2;

@implementation ClassA

...
justin
  • 104,054
  • 14
  • 179
  • 226
tikhop
  • 2,012
  • 14
  • 32

3 Answers3

3

extern

An extern constant/variable is one which one definition may be accessed (or referenced) across multiple object files. It's a global, exported C symbol. Use this if you want access to the constant/global variable from multiple translation units (or compiled files) or if you want to use it in multiple binaries (e.g. you want to use it from your app, and the definition is in a dynamic library). You will typically declare this in the header for others to use.

static

The static emits a copy for each translation. Each file that is compiled which also sees (e.g. is #included) the static will emit a copy of that static. You should avoid this. This will result in a bloated binary that has very confusing execution. You should favor the static if the value is local to a file, and should be private to that file.

For these reasons, you should favor static in your .c, .m, .cpp, and .mm files, and extern in your headers.

Finally, that NSString pointer should be const by default:

// declaration - file.h
extern NSString * const var1;

// definition - file.m
NSString * const var1 = @"var1";

or

static NSString * const var2 = @"var2";

If you still want more, here's a related answer I wrote, and here's another.

Community
  • 1
  • 1
justin
  • 104,054
  • 14
  • 179
  • 226
  • 1
    One could argue its a subtle point, but the `extern` qualifier does not itself declare a variable to have global visibility ("linkage" above) - a global variable without `extern` has global visibility. However if you choose to treat it as though it does you probably won't go wrong. Further details in my answer. – CRD Jan 12 '12 at 09:45
  • @CRD good point (+1), and good answer (+1). my answer provides an introduction to the subject. i avoided mentioning variables without qualification because there's no practical use for them (well, i favor explicit qualification…). – justin Jan 12 '12 at 10:21
  • depends how you define "practical". A good pattern for globals is one non-`extern` qualified definition in the code file that provides the global, and one or more `extern` qualified declarations which reference that global. I.e. an equivalent pattern to that for methods/functions - one place defines the body, one or more places reference the method/function with a prototype. In both cases "one or more" often means just in the header for the code file that defines the global/method/function. Now the relaxation *allows* you to add `extern` to the def, but it doesn't really make sense. – CRD Jan 12 '12 at 17:32
2

Global variables and static

Declaring a variable outside of any method (and in Objective-C either within, or outside, @implementation/@end makes the lifetime of the variable global, that is the variable will exist during the whole time period the application is executing.

A global variable with no qualification, or only with const and/or volatile qualifiers, is visible from anywhere. So for example:

NSString *MyApplicationName;

declares a global variable MyApplicationName which can be accessed from any place in the application.

The visibility of a global variable (but not its lifetime) can be restricted to just the file (more accurately "compilation unit" allowing for one file including others) containing the declaration by qualifying it with static. So for example:

static NSString *MyClassName;

declares a global variable MyClassName which is only visible from the current compilation unit.

Using static qualified global declarations within @implementation/@end is the closest thing Objective-C offers to other languages' "class variables".

You should not place global variable declarations, static qualified or not, in header files as that would result in multiple distinct declarations - an error will result if there is no static qualifier, and multiple distinct variables with different visibility scopes if there is one.

The extern qualifier

The extern qualifier does something rather different.

The original meaning (a small relaxation is now allowed, see below) is to just define the type and name of a global variable which is declared elsewhere. That is you are telling the compiler "there is a global variable of some type and name I'd like to use which will be supplied by another compilation unit". For example:

extern NSString *MyApplicationName;

states that some compilation unit contains the declaration (which must not be static qualified):

NSString *MyApplicationName;

The extern qualified declaration does not itself cause the allocation of any storage for the global variable.

You do place extern qualified declarations in header files, this is how a compilation unit advertises the global variables it wishes to export. You can also place them in code files to reference globals variables declared elsewhere. Within a code file you can place an extern qualified declaration either outside of any method/function - in which case the name/type is available for to whole compilation unit - or within a method/function - in which case the visibility of the name/type is limited to just that method/function.

The small relaxation

Originally you had to have one non-extern qualifier declaration to satisfy any extern qualified ones. However this was later changed, if on linking the various compilation units together none of them declare a global variable referenced by some extern qualified declaration then the linker (usually?) just generates the variable itself and adds it to the resultant binary rather than producing a "missing global" error. Best programming practice is not to rely on this relaxation - always have a none-extern qualified declaration for every global variable.

CRD
  • 52,522
  • 5
  • 70
  • 86
1

I could give an explanation, but it wouldn't be as good as this one:

http://blog.ablepear.com/2010/01/objective-c-tuesdays-static-variables.html

dtuckernet
  • 7,817
  • 5
  • 39
  • 54