It appears to me that even if I refer to a function in another file with out extern declaration, gcc can still compile that unit. So I am wondering whether the extern declaration is necessary anywhere for function? I know that you need extern for variables.
-
possible duplicate of [Effects of the extern keyword on C functions](http://stackoverflow.com/questions/856636/effects-of-the-extern-keyword-on-c-functions) – Ciro Santilli OurBigBook.com May 19 '15 at 07:36
4 Answers
functions have extern storage class specifier by default (unless they are explicitly defined as static)
extern Storage Class Specifier
If the declaration describes a function or appears outside a function and describes an object with external linkage, the keyword extern is optional. If you do not specify a storage class specifier, the function is assumed to have external linkage.
....
It is an error to include a declaration for the same function with the storage class specifier static before the declaration with no storage class specifier because of the incompatible declarations. Including the extern storage class specifier on the original declaration is valid and the function has internal linkage.

- 1
- 1

- 91,295
- 49
- 239
- 345
It's not necessary, but I prefer it in headers to reinforce the idea that this function is defined somewhere else.
To me, this:
int func(int i);
is a forward declaration of a function that will be needed later, while this:
extern int func(int i);
is a declaration of a function that will be used here, but defined elsewhere.
The two lines are functionally identical, but I use the extern
keyword to document the difference, and for consistency with regular variables (where the difference is important, and has exactly that meaning).

- 73,191
- 16
- 130
- 183
-
2I must say I find it extremely ugly in headers because it ends up making prototypes almost-surely longer than 80 characters, resulting in broken lines or horizontal scrolling, neither of which is pleasant. – R.. GitHub STOP HELPING ICE Mar 10 '11 at 04:48
-
@R.. - Debatable. It only takes up seven characters (including the space), which is rather little - it'd only give you room for an extra `const` or one parameter at most. It also depends on how many parameters you consider "too many." – Chris Lutz Mar 10 '11 at 04:53
-
so we can also make the assertions, "extern is there for backward convenience(don't mean compatibility) ? – Shamim Hafiz - MSFT Mar 10 '11 at 04:54
-
1Thanks for the answer. But another question is that even if I totally left the declaration out (including the extern keyword and the function prototype), it could still be compiled. – Xiaolong Li Mar 10 '11 at 05:00
-
1@Xiaolong Li - Not properly if the types were anything other than `int`s, and not in C99. – Chris Lutz Mar 10 '11 at 05:02
-
So I would better extern any function defined elsewhere, better in a header file? It seems that all the standard library header files doesn't use the extern keyword. Is that for any concern or just a style? – Xiaolong Li Mar 10 '11 at 05:08
-
@Xiaolong Li - Just a style, probably for the reason @R.. stated above. The "difference" is one I use to write better-documented code, but not one that is really necessary. – Chris Lutz Mar 10 '11 at 05:12
You do not necessarily "need" extern for variables.
When C was invented Unix linkers were also written, and they advanced the art in unheralded but clever ways. One contribution was defining all symbols as small "common blocks". This allowed a single syntax for declarations with no required specification of which module was allocating the space. (Only one module could actually initialize the object, but no one was required to.)
There are really three considerations.
Forward declarations for prototypes. (Optional, because legacy C has to compile without them.)
Extern declarations for non-function objects (variables) in all files except one. (Needed only on non-Unix systems that also have crummy linkers. Hopefully this is rare these days.)
For functions, extern is already the assumption if no function body is present to form a definition.

- 143,651
- 25
- 248
- 329
-
1The linkers on mainframes were far advanced over the dinky little Unix ld. The concept of "common" was in FORTRAN. – Jim Balter Mar 10 '11 at 07:49
-
1I agree about Fortran, and some linkers had lots of features. But you didn't want to use them, like extensive hierarchies of overlay support. On one of those "advanced" mainframe linkers there was a limit of 500 common blocks, but `ld(1)` could do one for every symbol. – DigitalRoss Mar 10 '11 at 17:14
-
Some people did want to use them, which is why they were there -- but overlays were not what I had in mind when I said those linkers were advanced. And increasing a limit is not an advancement of art in unheralded but clever ways. – Jim Balter Mar 10 '11 at 23:31
-
Ok, but it was the treatment of symbols that had the type of undefined but non-zero values as common blocks of the value's size that allowed the limit to go up. That one simple thing meant symbols needed only a few bits of type and a single value, but could merge declarations, decide between data and bss, merge data and bss, handle local and global versions of all of those, and detect multiple definitions. How about using the same format for input and output? And if those mainframe operating systems and linkers were any good, why are they buried so deeply and so forgotten now? – DigitalRoss Mar 11 '11 at 01:01
-
1Why is BetaMax buried so deeply and so forgotten now? And I said nothing about OS'es, but there's a whole lot of good one could say about Multics, and the Burroughs OS (written in Algol), but such things are lost on ideologues. – Jim Balter Mar 11 '11 at 22:41
-
@jimBalter: please mention something technical that's positive about those old pre `ld` linkers. So far, I'm supplying technical examples of my points while you have just been critical of my admiration for it. I've written linkers and I've made technical arguments here. You've just thrown mud and stated opinions. Can you up your game a little with some tech stuff? – DigitalRoss Apr 01 '16 at 18:42
As far as I remember the standard, all function declarations are considered as "extern" by default, so there is no need to specify it explicitly. That doesn't make this keyword useless since it can also be used with variables (and it that case - it's the only solution to solve linkage problems). But with the functions - yes, it's optional.
A little more verbose answer is that it allows you to use variables compiled in another source code file, but doesn't reserve memory for the variable. So, to utilise extern, you have to have a source code file or a library unit that contains memory space for the variable on the top level (not within functions). Now, you can refer to that variable by defining an extern variable of the same name in your other source code files.
In general, the use of extern definition should be avoided. They lead easily to unmanagable code and errors that hard to locate. Of course, there are examples where other solutions would be impractical, but they are rare. For example, stdin and stdout are macros that are mapped to an extern array variable of type FILE* in stdin.h; memory space for this array is in a standard C-library unit.

- 69
- 6