To understand the reasons behind the compiler behavior that seems so strange to you, you have to learn better about
variable scopes (can have a look
here[
^] and
here[
^]).
The variables in a C program have 3 main scopes:
Global, Local or parameter.
The scope is in effect the location, strictly circumscribable, where a variable can exist and be used.
A
global scope means that the variable can be accessed anywhere in your program, from inside and outside functions, and from any program module (file) that is included in your program.
But another very important property of the scope is that it allows the 'masking' of variables having same name, but different scope. Yes you can have more variables having the same name in the same piece of code, in the same file and even in the same function, but all of them must have
different scopes, and of course each scope
must be well identifiable or the compiler will throw errors.
Consider following code:
int var = 10;
void foo(void)
{
printf ("Inside foo. var=%d\n", var); }
void bar(int var)
{
printf ("Inside bar. var=%d\n", var); }
int main(int argc, char *argv[])
{
int var = 20;
do
{
int var = 5; printf ("Inside do-while. var=%d\n", var); } while(0);
printf ("Inside main. var=%d\n", var);
foo();
bar(7); }
Here we have 3 scopes: a global one in the very first line of the example, 2 local scopes (one in the function as very first function line, and one in the do-while block as inner local scope), and finally a parameter scope.
The compiler strategy is simply to use the most closer declaration.
Now if you run the example you will get:
Inside do-while. var=5
Inside main. var=20
Inside foo. var=10
Inside bar. var=7
As you can see the first output line shows the value in the do-while loop that is the closer declaration to the point where we access the variable.
On the second output line we have the value declared in the main function body, again the closer one.
On third output line we access the global value because there is no other declaration in the local block, and the closer scope is the global one.
On the last output line we have the parameter value that overrides the global one.
Now we go back the the global declaration: each variable declared outside a function scope is automatically created as global variable (unless you limit it to current module, file, using the
static qualifier), and is available over the whole program in all modules.
Please note that local and parameter variables declarations are always visible from the code that will use it, unlike the global declarations that can be declared in a module and used in another where there is no trace of it.
But how can we tell to the compiler that a variable we want to use exist somewhere in the program? Each module will not know of such a variable until when we will link all modules together, because only at that time we have access to all symbols defined over the modules.
The C language have a qualifier,
extern, that tells to the compiler that such a variable exists somewhere and it have not to complain, because the linker will solve all later... ;) The compiler when found this qualifier believe us and accept to compile the unit with no errors.
Now:
you cannot declare global variables inside a function or all scoping will not be applicable , so:
void main()
{
extern int n=10;
printf("%d",n);
}
It's an error!! Because the
extern qualifier tells to the compiler that we want declare a global variable.
While in:
#include<stdio.h>
extern int n=10;
void main()
{
printf("%d",n);
}</stdio.h>
The qualifier extern is redundant!!
I hope this clearified your mind now :)
P.S. to be more clear, if you write:
void main()
{
extern int a;
printf("%d",a);
}
In this case "
extern int a;" is used to inform the compiler that exists a global variable , 'a', somewhere in the program.
Just informs the compiler that the variable exist!
But if you write:
void main()
{
extern int a = 10;
printf("%d",a);
}
You not only inform the compiler (declaring the variable), but
you want also create and initialize the global variable inside a function. And, as I told before,
this is an error!!!!