extern
means that you are declaring something that is not (necessarily) defined here, but in some other units.
So extern int x;
doesn't allocate memory for a variable x
. It just declares to the compiler that, somewhere else in this code (may be in another compilation unit, that is another .c
file) that variable will be defined. That is that, somewhere else, there is a int x;
declaration.
This allows the compiler to know that it should not fail if some code uses x
. Instead of saying "x: symbol undefined", it will know that x
is some global variable of type int
, and compile any code referring to x
as such.
Then, of course, at some point, it will be necessary to check that, indeed, there is such a variable. But that is done at linking stage. That is, not when you compile, separately, each .c
file into a .o
file. But when you put all the .o
files, plus the libraries, together, to create an executable.
Understand that, mainly, this is what .h
file do: they contain, no code (I mean not code that should generate assembly code), but declarations. Declarations whose purpose is to give some contextual information for the compiler when compiling your .c
file.
Example
Let's consider an example case, in which you do, in a file testsin.c
extern double sin(double x);
int main(){
printf("%f\n", sin(1.0));
}
Then compile that file with gcc -c testsin.c
.
And then link the given .o
and the libm
library together, to create a testsin
executable, using gcc -o testsin testsin.o -lm
When compiling (gcc -c
) testsin
the compiler doesn't have any code about a sin
function, nor does it have any reason to know what you are talking about, and where this sin
function is.
Later, when linking (gcc -o testsin testsin.o -lm
) you'll provide the library that contains the sin
function (libm.so
, here passed with -lm
). But that is later. Without any DeLorean, it can't guess at compile time (gcc -c
) what this sin
thing is. So you must tell it "don't worry, don't raise an error, I swear this function exists, with this signature, and I will provide it to you later".
This, in C language, is said by the declaration extern double sin(double);
Now, of course, more realistically, what you would do is not that, but
#include <math.h>
int main(){
printf("%f\n", sin(1.0));
}
But that is the exact same thing. As its name suggest #include
just "copy&paste" the content of math.h
in your code. And math.h just contains some such declaration as extern double sin(double);
.
implicit extern
And I kept main information for the end, since I suppose, once all that clarified, that the reason why you are surprised to see this extern
, is that you have already seen some other code with simply double sin(double);
to do the same declaration.
Well, yes, extern
is implied for function declarations: if there is no code (no {...}
containing actula code), then extern
is implied any way.
It is for variables that you must always say it explicitly, because int x;
is the creation of the variable, not a declaration.
So, variable creation = int x;
. Function creation = double sin(double x){...}
Variable declaration = extern int x;
. Function declaration = extern double sin(double x);
OR double sin(double);
since that is unambiguous in this case.
As for your second question, I don't know (and anyway, rule around here is that you are supposed to ask a single question). But it is quite usual to have some "private" implementation of functions, in internal code, for example specific to an architecture, named with some _
, and then, in some other places, a simple alias to make somefunc
point to __someprefix_somefunc_somesuffix_
or thing like that.