static const Vs extern const

ssh88 picture ssh88 · May 14, 2014 · Viewed 11.2k times · Source

I have been using static const in my header files as so:

static NSString * const myString = @"foo";

But have read that this is not the 'safe' or correct way of doing this. Apparently, if I want my const strings to be accessed from another class, I should be declaring the string in my .h as:

extern NSString * const myString;

Then in my .m file:

NSString * const myString = @"foo";

Is this correct? If so, what is the reason not to declare it as static directly in my .h file? It works perfectly fine, and I can not see any 'safety' issues around this. It is a const, so therefore it can not be changed from outside and its something I intentionally need accessed outside of the class. The only other thing I can think of is that to hide the value of the string?

Answer

Martin R picture Martin R · May 14, 2014

Your first variant

static NSString * const myString = @"foo"; // In .h file, included by multiple .m files

defines an myString variable locally in each "translation unit" (roughly speaking: in each .m source file) that includes the header file. All string objects have the same contents "foo", but it may be different objects so that the value of myString (the pointer to the string object) may be different in each unit.

Your second variant

extern NSString * const myString; // In .h file, included by multiple .m files
NSString * const myString = @"foo"; // In one .m file only

defines a single variable myString which is visible "globally".

Example: In one class you send a notification with myString as user object. In another class, this notification is received and the user object compared to myString.

In your first variant, the comparison must be done with isEqualToString: because the sending and the receiving class may have different pointers (both pointing to a NSString object with the contents "foo"). Therefore comparing with == may fail.

In your second variant, there is only one myString variable, so you can compare with ==.

So the second variant is safer in the sense that the "shared string" is the same object in each translation unit.