In this article, we’ll take a look at understanding the extern keyword in C.
This is primarily used when you have multiple source files, and you want to share variables among those files.
Let’s take a look at how we can use extern
properly, to compile all our files without conflicts.
What does the extern keyword do?
Before we look at extern
, let’s look at two types of statements first:
- A variable declaration statement
- A variable definition statement
A declaration statement is something like this:
1 2 |
int a; char* ch; |
You inform the compiler that these variables exist somewhere already, so it does not allocate memory separately for them. This is a crucial point.
There is another statement for defining a variable, where you explicitly allocate storage for that particular variable.
To define a variable, we typically do something similar to the below snippet.
1 2 3 4 |
// Defining a int a = 10; // Defining ch, even if it is NULL char* ch = NULL; |
Now, let’s move on to extern. We can use the extern keyword only when we are declaring a global variable. Let’s make this clear.
This means that you cannot prefix the extern keyword when defining a global variable.
1 2 3 4 |
// Allowed. Variable declaration extern int a; // Not allowed. extern with variable definition extern int b = 5; |
To understand why, let’s look at what extern
actually means.
When you’re prefixing a global variable declaration with an extern
keyword, this means that you’re telling the compiler that this variable is actually defined in some other file!
This means that the compiler does not need to allocate the same shared variable twice, and this will not cause conflict when working with multiple source files.
Using the extern keyword in C – A complete example
Let’s look at an example to make this clear.
Assume that we have two source files and two header files:
file1.c
,file1.h
file2.c
file2.h
.
Assume a separate main program called main.c
, which is the driver program.
So let’s consider file1.c
, which has a global variable called int file1_var
defined. So, we intend to share this to file2.c
using extern
.
I’ll provide sample code for file1.h
, which has a simple function prototype for the functions of file1.c
, so that other programs can find out which function to invoke, when including the header file file1.h
.
1 2 3 |
// file1.h // Contains function prototypes for functions of file1.c int addition_1(int a, int b); |
1 2 3 4 5 6 7 8 9 10 11 12 13 |
// file1.c // Contains function definition for addition_1() #include "file1.h" #include <stdio.h> // Also has a global variable called file1_var // We are defining it here so that it can be shared by other files // when they use extern on this variable int file1_var = 100; int addition_1(int a, int b) { file1_var = file1_var + 100; printf("Inside file1.c addition(). file1_var = %dn", file1_var); return a + b; } |
I have set the initial value of file1_var
as 100.
Similarly, I will do the same for file2.h
and file2.h
. But now, since we want a reference to file1_var
, we need to use extern
, and only declare it.
1 2 |
// file2.h int addition_2(int a, int b); |
1 2 3 4 5 6 7 8 9 10 11 |
// file2.c // Contains function definition for addition_2() #include "file2.h" #include <stdio.h> // Makes an extern reference to file1_var extern int file1_var; int addition_2(int a, int b) { file1_var = file1_var + 200; printf("Inside file2.c addition(). file1_var = %dn", file1_var); return a + b; } |
Now, the two files share a variable file1_var
, which also gets updated when any of the addition()
functions gets called.
Let’s write the code for the driver program main.c
, which calls both functions. So, we must include both header files file1.h
and file2.h
.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
#include "file1.h" #include "file2.h" #include <stdio.h> // We can also use the file1_var reference here! extern int file1_var; // We must have only one main() reference // Since this is our driver program, the main function must be only here int main() { int res1 = addition_1(10, 20); int res2 = addition_2(30, 40); printf("file1_var = %dn", file1_var); return 0; } |
I’ll be using gcc
to compile all our files:
1 |
gcc -o main.out main.c file1.c file2.c |
This command compiles and links the files main.c
, file1.c
and file2.c
, and creates an executable called main.out
.
To execute, type ./main.out
.
1 |
./main.out |
Output
1 2 3 |
Inside file1.c addition(). file1_var = 200 Inside file2.c addition(). file1_var = 400 file1_var = 400 |
The output indeed seems to match what we expect. file1_var
will get incremented by 100, when addition_1()
gets called.
Now, again, it will increment by 200, when addition_2()
gets called. So finally, the updated value of file1_var
is 400!
We have successfully used extern
to share variables between multiple source files!
NOTE: To understand more about compiling and using multiple source and header files, refer this link. This mentions the best practices to avoid re-declaration errors when linking multiple files, so please read this too.
Conclusion
In this article, we learned how we could use the extern keyword in C++ to share variables across source files. This is essential if you’re working with multiple files and global variables.