You need to distinguish between two separate concepts: function definition and symbol declaration. "extern" is a linkage modifier, a hint to the compiler about where the symbol referred to afterwards is defined (the hint is, "not here").
If I write
extern int i;
in file scope (outside a function block) in a C file, then you're saying "the variable may be defined elsewhere".
extern int f() {return 0;}
is both a declaration of the function f and a definition of the function f. The definition in this case over-rides the extern.
extern int f();
int f() {return 0;}
is first a declaration, followed by the definition.
Use of extern
is wrong if you want to declare and simultaneously define a file scope variable. For example,
extern int i = 4;
will give an error or warning, depending on the compiler.
Usage of extern
is useful if you explicitly want to avoid definition of a variable.
Let me explain:
Let's say the file a.c contains:
#include "a.h"
int i = 2;
int f() { i++; return i;}
The file a.h includes:
extern int i;
int f(void);
and the file b.c contains:
#include <stdio.h>
#include "a.h"
int main(void){
printf("%d\n", f());
return 0;
}
The extern in the header is useful, because it tells the compiler during the link phase, "this is a declaration, and not a definition". If I remove the line in a.c which defines a, allocates space for it and assigns a value to it, the program should fail to compile with an undefined reference. This tells the developer that he has referred to a variable, but hasn't yet defined it. If on the other hand, I omit the "extern" keyword, and remove the int i = 4
line, the program still compiles - i will be defined with a default value of 0.
File scope variables are implicitly defined with a default value of 0 or NULL if you do not explicitly assign a value to them - unlike block-scope variables that you declare at the top of a function. The extern keyword avoids this implicit definition, and thus helps avoid mistakes.
For functions, in function declarations, the keyword is indeed redundant. Function declarations do not have an implicit definition.