C Programming: Experimenting with extern

4 minute read

So, finally a programming post onย  a computer science blog ๐Ÿ™‚ . And it is about one of the most dreaded and misunderstood keywords that the founders of C ever produced โ€“ it is about the extern keyword. I will try my best to remove the dread and sort out the misunderstanding. So, lets get started then.

To understand the extern keyword, you must first understand the difference between declaration and definition.

Declaration:

Declaration is a way of making the compiler know that the declared entity(variable/function) does exist and its definition will be found later โ€“ in a separate file, or in the same file, or in a library that will be linked at link time. No memory is allocated to the entity at the time of declaration.

Definition:

Definition of an entity is what allocates memory for that entity.

The One Definition Rule(ODR):

The ODR states that a variable or a function can have multiple declarations in a compilation unit but only a single definition โ€“ Canโ€™t allocate memory twice for the same thing.

So lets see some examples:

int fun(int, int);

The above statement simply declares a function named fun that takes two integer arguments and returns an integer.

int fun(int a, int b)
{
    return (a + b);
}

The above snippet is the definition of the declared function fun.ย Now consider the statement below:

int a;

The above statement is both, declaration and definition of an integer variable named a. In fact without the use of extern, there is no way you can only declare a variable. So, lets dive into extern now.

When we declare an entity as extern, it can be used across all the files in the program provided a declaration for that is provided in that file.

extern in functions:

In C, all functions are by default extern and thus can be used across files in the program. So, if you declare a function as:

extern int fun(int, int );

The extern is redundant.

extern in variables:

This is how you declare a variable as extern:

extern int a;

Also note that all global variables are extern by default.

#include<stdio.h>
extern int a;
int main()
{
    printf("%d\n", a);
    return 0;
}

The above program will give linker error as a is not defined or allocated memory yet and we are trying to access it. So, to define a write the following outside all functions:

int a = 5;

The value 5 is optional and if not given a has value 0.

So, now lets see an example:

#include<stdio.h>
extern int i; //declaration of i.
void fun()
{
	printf("%d\n", i);
}

int main()
{
	extern int i; //declaring that the i main uses is the global(extern) one.
	i++;
	fun();
	return 0;
}
int i = 5; //definition and initialization of i.

The output of the above program will be 6, since i++ works on the global i.

But if we remove the extern from the first line in main, the output will be 5, as i++ will then work on the local i.

Now, consider the following code:

#include<stdio.h>
extern int a = 5;
int main()
{
    printf("%d\n", a);
    return 0;
}

The above program works just fine without any error and prints 5. Why?? Well according to the C standard:

We can provide an initializer on a variable defined as extern. An extern that has an initializer is a definition. It is an error to provide an initializer on an extern inside a function.

So, the first two sentences explain why the above code works. But, what about the sentence in bold. It says that if we write the extern line inside main instead of outside, it will give error. Well, this does make sense to not allow extern inside any function. Lets see an example to clarify that:

#include<stdio.h>
extern int i;
void fun()
{
	extern int i = 10; //line 1
	printf("%d\n", i);
}

int main()
{
	extern int i;
	i++;
	fun();
	return 0;
}
int i = 5;

In the above code, had line 1 in fun not been an error, then what should have been the output?? 6 or 10. Is i defined twice?? So, you see there is no way to make sense of this and hence extern should always be globally defined variables.

So, now lets experiment with extern a bit to understand it deeper:

Consider the following code:

#include<stdio.h>
extern int i;

int main()
{
	int i = 2;
	printf("%d\n", i);
	return 0;
}
int i = 5;

The above program is quite simple and prints the local iโ€™s value i.e. 2. But what if you want the global value in main?? The solution is written below:

#include<stdio.h>
extern int i;

int main()
{
	int i = 2;
        printf("%d\n", i);
	{
		extern int i;
		printf("%d\n", i);
	}
        printf("%d\n", i);
	return 0;
}
int i = 5;

The above program prints 2, then 5 and then 2.ย The line extern int i, brings the extern i into scope for the block inside main. Outside the curly braces though, the i is still the local one.

So, I hope I was able to clarify extern to you people, at least a little bit through this post. Thank you for reading, comment if you want to say something. And also once again, below is the form to subscribe to updates via mail.

[subscribe2]

Leave a Comment