The keyword static and extern have been commonly to limit the storage duration and linkage of variables and functions in C.
In this blog post, I would like to quickly discuss static and extern in C and show a self-explanatory example.
Static and Extern
The keyword static and extern affects the storage duration a variable and the linkage of a variable or a function.
static - static duration and internal linkage
extern - static duration and external linkage
The static storage duration is the entire execution of the program, and the value stored in the object is initialized only once, prior to main function.
With internal linkage, the identifier can be referred to from all scopes in the current translation unit. All static file-scope identifiers (both functions and variables) have this linkage.
With external linkage, the identifier can be referred to from any other translation units in the entire program. All non-static functions, all extern variables (unless earlier declared static), and all file-scope non-static variables have this linkage.
Example
Here is a self-explanatory example on demonstrating the use cases of static and extern.
/* Static variable is local to this file. */ /* other files can also have a variable of the same name. */ staticint i = 0;
/* External variable j from other files. */ externint j;
/* Static function local to this file. */ staticvoidhello_heaven() { printf("-----------------------------------------------\n"); printf("hello_heaven called from lib\n"); }
/* extern void hello_world(); */ /* extern is not needed since declaration always refers extern for * implementation. */ voidhello_world();
/* Static function shortcut */ voidhello_heaven_shortcut() { hello_heaven(); }
int a = 5;
voidhello_underworld() { staticint k = 0; i++; j++; k++; printf("-----------------------------------------------\n"); printf("hello_underworld called from lib\n"); printf("static variable i from lib: %d\n", i); printf("extern variable j from lib: %d\n", j); printf("static variable k from lib hello_underworld: %d\n", k); hello_world(); }
/* multiple definition of `a' during linking since it's defined elsewhere */ /* int a = 10; */
voidhello_world() { i++; j++; printf("-----------------------------------------------\n"); printf("hello_world called from main\n"); printf("static variable i from main: %d\n", i); printf("extern variable j from main: %d\n", j); }
intmain() { /* undefined reference to `hello_heaven' during linking since it's static in * lib.c */ /* hello_heaven(); */ hello_heaven_shortcut(); hello_world(); hello_world(); hello_world(); hello_underworld(); hello_underworld(); }
$ gcc -c lib.c -o lib.o $ gcc -c main.c -o main.o $ gcc -o main main.o lib.o $ ./main ----------------------------------------------- hello_heaven called from lib ----------------------------------------------- hello_world called from main static variable i from main: 1 extern variable j from main: 1 ----------------------------------------------- hello_world called from main static variable i from main: 2 extern variable j from main: 2 ----------------------------------------------- hello_world called from main static variable i from main: 3 extern variable j from main: 3 ----------------------------------------------- hello_underworld called from lib static variable i from lib: 1 extern variable j from lib: 4 static variable k from lib hello_underworld: 1 ----------------------------------------------- hello_world called from main static variable i from main: 4 extern variable j from main: 5 ----------------------------------------------- hello_underworld called from lib static variable i from lib: 2 extern variable j from lib: 6 static variable k from lib hello_underworld: 2 ----------------------------------------------- hello_world called from main static variable i from main: 5 extern variable j from main: 7