24
  1. When I use the word extern before a method or variable declaration, am I making it global and therefore readable/writable/usable over the entire project ?

  2. If I use extern before a keyword, is there any chance it is still not accessible by part of my project ? For example, only by subclasses.. such as when I use "protected".

  3. extern is a C keyword, right? Is there an equivalent in Objective-C? I actually don't understand why they use a C keyword in an Objective-C project.

thanks

rounak
  • 8,669
  • 3
  • 38
  • 58
aneuryzm
  • 55,858
  • 96
  • 259
  • 471
  • 3
    Objective-C is a superset of C. So the C keywords apply. – Mat Sep 07 '11 at 07:07
  • @Mat I know, but my point was: isn't objective-c providing its own keywords to declare globals methods and variables ? – aneuryzm Sep 07 '11 at 07:15
  • 2
    @Patrick: what I meant is that "extern is C keyword right ? Is there an equivalent in Objective C ?" doesn't really make sens. The Objective-C equivalent to the C `extern` is... `extern`. See also [Use of extern in Objective C](http://stackoverflow.com/questions/1946296/use-of-extern-in-objective-c) (and the 4 or 5 top related questions on this page) – Mat Sep 07 '11 at 07:18

3 Answers3

39

1) you're specifying its linkage. extern linkage allows you or any client to reference the symbol.

regarding global variables: if the variable is mutable and/or needs proper construction, then you should consider methods or functions for this object. the notable exception to this is NSString constants:

// MONClass.h
extern NSString* const MONClassDidCompleteRenderNotification;
// MONClass.m
NSString* const MONClassDidCompleteRenderNotification = @"MONClassDidCompleteRenderNotification";

2) there is no case where the extern keyword affects visibility (public/protected/private/package). to use the symbol (e.g. the constant or C function), simply include the header it is declared in.

somewhat confusing if you are new to the language: placing extern C declarations (constants, functions) in between @interface ... @end will not alter its scope:

@interface MONClass : NSObject

extern const size_t MaximumThreads;

@end

has the same scope (global) and visibility (public) as:

@interface MONClass : NSObject

@end

extern const size_t MaximumThreads;

so it really makes no sense to place your class related C constants or functions in the @interface...@end and @implementation...@end. i recommend placing these in the same header as the interface, outside @interface/@end and @implementation/@end and prefixing the name with the class it is associated with, like so:

@interface MONClass : NSObject

@end

extern const size_t MONClassMaximumThreads;
// MONClass.m
const size_t MONClassMaximumThreads = 23;

and if you want that constant to be private, just declare and define it like this:

// MONClass.m
static const size_t MONClassMaximumThreads = 23;

@implementation MONClass

@end

unfortunately, there is no equally simple or common way to make this constant protected with objc.

finally, you can also use class methods if the number should vary by class:

@interface MONMammal : NSObject
+ (NSUInteger)numberOfLegs;
@end

@implementation MONDog
+ (NSUInteger)numberOfLegs { return 4; }
@end
@implementation MONHuman
+ (NSUInteger)numberOfLegs { return 2; }
@end

3) yes, among other languages. for example, if you use extern const int Something in a c++ translation, the c++ translation will look for Something declared as an extern C++ symbol. there is no substitution in objc; objc is a superset of C and inherits all of C's functionalities. use of extern is well formed and you can also find it in the frameworks you use (e.g. Foundation). they use it because they need to specify linkage. objc does not offer a substitute, presumably because it did not require a replacement or extension.

to avoid this, simply use a #define like this:

#if !defined(__cplusplus)
#define MONExternC extern
#else
#define MONExternC extern "C"
#endif

MONExternC const size_t MONClassMaximumThreads;
justin
  • 101,751
  • 13
  • 172
  • 222
  • 2
    A couple of notes from the perspective of class declarations: wrt 1), there’s no such thing as an `extern` method in Objective-C; wrt 2), and related to 1), it doesn’t apply to class hierarchies. –  Sep 07 '11 at 07:23
  • @Bavarious hmm... i didn't specify that methods are extern, only *exported*. i'll reread it tomorrow -- i'm pretty tired atm. it may just be worded poorly :) feel free to edit it, if you like. – justin Sep 07 '11 at 07:53
  • Just (hopefully!) making it a tad clearer for the OP (and, after 24 hours awake, I’m not even considering answering). –  Sep 07 '11 at 07:55
  • k - will try to improve the signal to noise ratio after i've had some sleep =) – justin Sep 07 '11 at 07:58
  • @Bavarious Thanks for answers, despite of lack of sleeping. What I don't understand is the following: can't I just declare static methods/variables? or use a singleton ? – aneuryzm Sep 07 '11 at 08:23
  • @Pat There’s no such thing as static methods and `extern` applies only to the part of Objective-C that’s plain C, i.e., nothing related to classes and class hierarchies. Having a singleton or a public class method or a public instance variable isn’t related to `extern`. –  Sep 07 '11 at 08:26
  • @Bavarious. Yeah I understand that extern is not related to classes. Altrnatively, can I just use a class to store all my "globals" variables and methods and use class variables and class methods to get them ? Is more or less convenient than using extern ? – aneuryzm Sep 07 '11 at 08:42
  • @Pat Ah, now I get what you want. I personally do the following: global **constants** as `extern`, normally with scalar data types. If something is global but isn’t constant, then I use a class to control access (including locking/synchronisation) to the global values. I prefer to use instance methods because it makes it easier to have different instances with different values, which might be an issue if those globals need to be thread-specific, or in test cases. –  Sep 07 '11 at 08:46
  • MONExternC can be replaced with native UIKIT_EXTERN – Cœur Jun 27 '14 at 15:12
  • @Cœur sometimes, but not generally ideal: http://stackoverflow.com/questions/17668018/when-to-use-uikit-extern-vs-just-extern – justin Nov 21 '14 at 08:06
  • The `#if !defined(_cplusplus)...` case can be avoided by using `FOUNDATION_EXPORT`, see [here](http://stackoverflow.com/a/10953284/1161906). – bcattle Jan 13 '15 at 05:23
  • 1
    @bcattle i generally recommend a library defines its own definition. it's best to avoid introducing dependent libraries for these simple definitions. See: http://stackoverflow.com/questions/17668018/when-to-use-uikit-extern-vs-just-extern/17669269#17669269. and yes, i have encountered several programs that incorrectly assumed another library (e.g. Foundation, UIKit, AppKit, etc.) would be visible/available. it's not good for portability, reuse, or build times. it also prevents c translations from using the header (which may be reasonable or not, depending on what's declared in that header). – justin Jan 14 '15 at 04:26
17

extern doesn't mean "global", it means "defined elsewhere". It is used to tell the compiler that a variable or function exists (in another object file or library), so that it shall not complain about it and that the linker will be provided with that object file or library.

As a consequence extern implies that the target item is global.

Objective-C is just a superset of C. Everything that is available in C is available in Objective-C as well, with the same syntax and semantic. There is no construct of C that is defined in another way in Objective-C.

mouviciel
  • 62,742
  • 10
  • 106
  • 135
  • Thanks. So, do I always need to import the header containing the extern statement, if I want to use the extern method/variable ? – aneuryzm Sep 07 '11 at 08:18
  • In other terms, can I just store my extern methods/variables in a class and import its header when I need to use them ? As alternative can't just use static methods or variables from a singleton ? – aneuryzm Sep 07 '11 at 08:20
  • 1
    `extern` does not apply to methods or instance variables, it applies to functions or variables outside the scope of a class. – mouviciel Sep 07 '11 at 08:22
  • I see ok. So, last question. Is extern more convenient then declaring static methods or variables ? I need to import the header file anyway, correct ? – aneuryzm Sep 07 '11 at 08:28
  • The header file should contain variables that are declared `extern`. Writing an `extern` declaration in your .m file or importing it from a .h file depends on how your code is organized. – mouviciel Sep 07 '11 at 08:46
0

Point 3: Yes you can use FOUNDATION_EXPORT in objective C which is a macro that resolves to different keyword depending if compiling C or C++

More info here on the differences: "FOUNDATION_EXPORT" vs "extern"

Community
  • 1
  • 1
Vlad
  • 4,915
  • 3
  • 32
  • 56