The other answers are correct, but it's not quite accurate to say that the static function is not accessible from another file. It is possible to access the function through a function pointer. It would be more accurate to say that the name of the function is not accessible in another translation unit.
Remember that converting C source code to an executable program consists of conceptual stages, including:
- preprocessing (in which
#include
directives are replaced with the contents of the included file
- compilation (which processes one translation unit at a time)
- linking (in which the translation units are put together into the final program)
Suppose we have three files. foo.h
:
typedef void (*void_function_p)(void);
extern void_function_p foo(void);
foo.c
:
#include "foo.h"
#include <stdio.h>
static void baz(void) {
printf("worked!\n");
}
void_function_p foo(void) {
return baz;
}
bar.c
:
#include "foo.h"
#include <stdio.h>
int main(void) {
(*foo())();
return 0;
}
This program compiles and prints "worked!" when it runs.
There are two translation units here. One is the code in the preprocessed foo.c
(which, because of how #include
works also includes the code in foo.h
and stdio.h
). The other is the code in the preprocessed bar.c
(which, again, has its own copy of the code in foo.h
and stdio.h
).
By having the function foo
return a pointer to the static function baz
, we are able to call baz
from the main
function.
Now, consider what happens if we modify main
to look like this:
int main(void) {
(*foo())();
baz();
return 0;
}
This code will result in a linker error because the name baz
in this translation unit cannot be linked to the definition of baz
in the other translation unit.
This is the first advantage of static functions: another programmer cannot accidentally access our baz
function from another translation unit.
Now, consider what happens if we modify bar.c
to look like this:
#include "foo.h"
#include <stdio.h>
static void baz(void) {
printf("still works!");
}
int main() {
(*foo())();
baz();
return 0;
}
This code will compile, and print "worked!" followed by "still works!"
This is the second advantage of static functions: we've defined two functions (in different translation units) with the same name.
If you try to put both static definitions in the same translation unit, you will get a compiler error about defining baz
twice.
As a final note, if you take the program as it now stands and remove all the static
s, it will result in a linker error because baz
has been defined twice (with external linkage), which is not permitted.