How are extern variables defined? - c

I have a few doubts regarding the use of extern keyword with variables in C. I did go through the links related to this question. However, there are still a few things that I didn't gather very well
#include<stdio.h>
main( )
{
extern int i;
printf ( "\n%d ",i) ) ;
}
int i = 31 ;
In the above code, how does I get printed before its definition statement?
Now in the following code:
#include<stdio.h>
int x = 21 ;
main( )
{extern int i;
i=20;
printf ( "\n%d ", i ) ;
}
Isn't the statement "i=20;" a definition statement? I get an error for this. Is it because i'm trying to change the variable that is defined in some other source file? If this is the case how is the statement "int i=31;" in the top most code snippet right to use?
Also, I read, "int i;" is a definition. I don't really follow how.

In your first program, the print statement is printing the value of i based on the extern int i declaration. This is similar to calling a function based on its prototype declaration without seeing its definition. The compiler generates code to retrieve the value in the global variable named i. The symbol is resolved to the correct variable and address at link time.
In your second program, no definition for i is provided, only the extern int i declaration, and the attempt to set its value with i = 20. At link time this fails, since there is no definition, and so the attempt to resolve the reference to the global variable fails. Changing i = 20 to int i = 20 instead creates a local variable named i within the scope of the function main(), and is no longer referencing the globally declared extern int i.
When int i; is used at global scope, it is treated as a declaration and may be treated as a kind of definition. A global variable declared with an initializer, like:
int i = 20;
is always treated as a definition. Only one definition of this type is allowed, even if each is using the same initializer value. However,
int i;
is treated like a declaration. If more than one of these declarations appear, they are all treated as declarations of the same variable. At the same time, if no declaration with an initializer is present, this variable is implicitly defined with an initializer of 0, and the linker will be able to resolve references to it.

Declaration of a variable/function simply declares that the variable/function exists somewhere in the program but the memory is not allocated for them.
Coming to the definition, when we define a variable/function, apart from the role of declaration, it also allocates memory for that variable/function.
So in the 1st program, int i = 31 outside the main() defines the variable i. This variable is then merely declared as an extern variable inside the main(). Hence the program works.
In the 2nd program, without defining the variable i elsewhere, it is directly declared as an extern variable. Hence it gives an error.

In the second program you haven't defined the variable anywhere , not outside the main and instead you have defined it inside main so you are getting that error.
But in the first program you are defining the variable once and that is outside the main so you don't get that error.Program looks outside the main and find its definition.
int i; is a variable definition declaration both for AUTO variables (i.e inside main or any function ) but not for the external variables for extern variables you have to declare it like :
extern int i;
and then define outside main like this :
int i;

The idea behind extern is that you tell the compiler you're going to use a variable that was already defined outside the scope of where it is used.
It doesn't make much sense in your second case as there i is defined as a local variable.
If you were to define it as a global, like you do in the first case, it would be fine.
If I can demonstrate the use of extern with a very simple (contrived) case:
main.c:
#include <stdio.h>
extern int a; /* we tell the compiler that a will come from outside the scope of where it is used */
int main()
{
printf("%d\n", a);
return 0;
}
source.c:
int a = 3; /* we define a here */
You then compile both .c files like this:
$ gcc main.c source.c
This outputs 3.
You might also want to have a read at this article.

Related

understanding the extern keyword in c

#include <stdio.h>
int main()
{
extern int a;
extern int a;
int a = 10;
return 0;
}
what is the problem with this code? Since multiple declaration is allowed in c what is the problem with this code
The problem with the code is that the compiler is first informed that a is a global variable (due to the extern keyword); and then a is defined as a local 'automatic' variable. Hence there is a conflict in the defined scope of a
As an alternative to automatic variables, it is possible to define variables that are external to all functions, that is, variables that can be accessed by name by any function. (This mechanism is rather like Fortran COMMON or Pascal variables declared in the outermost block.) Because external variables are globally accessible, they can be used instead of argument lists to communicate data between functions. Furthermore, because external variables remain in existence permanently, rather than appearing and disappearing as functions are called and exited, they retain their values even after the functions that set them have returned. —The C Programming Language
An external variable must be defined, exactly once, outside of any function; this sets aside storage for it. The variable must also be declared in each function that wants to access it; this states the type of the variable. The declaration may be an explicit extern statement or may be implicit from context. ... You should note that we are using the words definition and declaration carefully when we refer to external variables in this section. Definition refers to the place where the variable is created or assigned storage; declaration refers to places where the nature of the variable is stated but no storage is allocated. —The C Programming Language
From your question I observe that you are visualizing your program something like this
#include <stdio.h>
int main()
{
extern int a; //declaration
extern int a; //declaration
int a = 10; //declaration + definiton
return 0;
}
With above understanding of extern keyword. Your question is obvious.
Let us understand use extern of keyword thoroughly.
Extern variable declaration is a promise to the compiler that there would be a definition of a global variable some place else. Read This. In other words extern keyword tell the compiler that forget about this variable at the moment and left it to linker to link it with its definition. That is extern variables are actually linked to its definition by linker. Moreover Local variables have no linkage at all. So while searching for its definition compiler found a definition without linkage. Thats the error.
As a rule of thumb just remember when you declare any variable as extern inside any function then you can only define it outside of that function.(However there is no use of it).

Problems compiling program with extern variable

Inside main() function when I create a separate block (new pair of curly braces) like this one-:
int main(void){
int x = 10;
{
extern int y;
printf("\tNo. is %d\n", y);
int y = 20;
}
}
When I compile this code I come across an error :
test.c: In function ‘main’:
test.c:12:9: error: declaration of ‘y’ with no linkage follows extern declaration
int y = 20;
test.c:9:16: note: previous declaration of ‘y’ was here
extern int y;
But
If the definitaion for int y is placed at end of the main function the code compiles and run perfectly okay.
What could be reason behind this error? According to my book if a variable is declared as extern then we can use it before defining it and the compiler will search in the whole file for definition of the variable.
C distinguishes variables in file scope (= outside any function) and variables in a local scope.
The y-variable that you declare with extern and use in the printf refers to a variable in file scope. That variable is only declared and must be "defined" elsewhere. That is storage must be allocated for it.
If you you have the second declaration of y inside any of the {} this is a local variable that is different from the file scope variable. If it is outside, it is a declaration of a file scope variable and a "tentative definition" of that file scope variable. So in this later case you have a declaration that is visible where the variable is used, and somewhere else a definition such that storage is provided, and everything works fine.
You can't declare a variable with identical name twice in a block with same block scope.
yes there is problem there when you used extern there. that means this int y is defined globally in the same file or different file. but without defining y (globally) you are printing that extern value that's why its error for linker

Strange behaviour of extern in c

I am surprised with the following behaviour of extern.
When I run this
#include<stdio.h>
int main()
{
extern int a;
printf("%d\n", a);
return 0;
}
int a=20;
OUTPUT: 20(in gcc Linux 32-bit,which seems OK)
But when I declare the variable a inside main():
#include<stdio.h>
int main()
{
extern int a;
int a=20;
printf("%d\n", a);
return 0;
}
OUTPUT:
extern.c: In function ‘main’:
extern.c:5:9: error: declaration of ‘a’ with no linkage follows extern declaration
extern.c:4:16: note: previous declaration of ‘a’ was here
Why I am getting the error now after changing the scope of a from global to local?Why it now doesn't allow redeclaration of a ,whereas it allowed in previous case.
The point of an extern declaration is to tell the compiler about a global variable or function used by multiple compilation units (.c files), but defined and allocated in a single compilation unit. The extern declaration is placed in a header file included by all units, and a single compilation unit contains the actual definition, therefore seeing both.
Your first example is legal C: you are declaring that a will refer to an externally defined variable, and then proceed to define that variable in the current compilation unit. Normally the extern declaration would be included from a header file and therefore appear to the compiler on top-level, not inside the function, but the compiler doesn't care either way. In other words, here there is no redefinition, only definition following declaration.
Your second example declares a to have external linkage, and then proceeds to define it as a local variable in main. The declaration and the definition are obviously incompatible - if a is a local variable, it cannot be defined and allocated in only one place - it will instead be automatically allocated on the stack every time the function is called. This incompatibility results in the error diagnostic.
In the first example, you are telling to the compiler: "hey, I have this variable called a that is defined somewhere else.", and then you use it. That's fine.
#include<stdio.h>
int main()
{
extern int a;
printf("%d\n", a);
return 0;
}
int a=20;
In the second example, you are also telling to the compiler that there is somewhere in the program a variable called a you want to use, and then you declare a new variable with the same name on your stack. That does not make much sense and the compiler says 2 things: can't find any declaration of variable a in the program and variable a already exists (if you fix the first error, it will).
#include<stdio.h>
int main()
{
extern int a;
int a=20;
printf("%d\n", a);
return 0;
}
When you declare a global variable, its memory is allocated when the program is launched (it's in the binary file and mapped in memory). When you declare a local variable, the memory is allocated on the stack, during the execution of the function. You can't refer with extern to a variable that does not exist yet.

Use of 'extern' Keyword [duplicate]

This question already has answers here:
How do I use extern to share variables between source files?
(19 answers)
Closed 9 years ago.
i am confused in the use of extern keyword in C. when it is used with a variable, then it means the declaration of variable. I declare the variable tmp outside the main() function and define it in a separate block in main but when i print the value in subsequent block i got an error "UNRESOLVED EXTERNAL LINK". I am confused please give me detailed explanation.
#include <stdio.h>
extern int tmp ;
int main()
{
{
int tmp = 50;
}
{
printf("%d",tmp);
}
return 0;
}
No; extern int tmp; means "somewhere else there is a definition of the variable tmp"; this is a declaration — you can reference tmp but it is not defined. Further, when you write extern int tmp; outside a function, it means that the variable will be defined outside a function — it is a global variable which may be defined elsewhere in the current source file or in another source file. (The rules for extern int tmp; written inside a function are moderately complex; let's not go there now!)
Your local variable int tmp = 50; in the function is unrelated to the global variable tmp declared outside. The local variable hides the global variable inside the braces. (The local variable is also unused.) The printf() statement, though, references the global variable; the local variable is not in scope for the printf().
Because you do not define the global variable (for example, by adding int tmp = -2; at the bottom of the file), your program fails to link and will continue to do so until you either define the variable in this source file or link in another source file where the variable is defined.
This line :
extern int tmp ;
says look for the tmp variable definition elsewhere , which means look for the variable definition in other translation unit in the entire program.
when you define int tmp in main it is local to that function, i.e it doesn't have any external linkage.
Disclaimer- There are seriously many posts on SO regarding this like the one with link provided in the comments above . No, matter how much I add to this it will end up being a repetition. however , you have a good answer below by Jonathan leffler too.
Extern is redeclaration
, so it doesn't crate variable, but only tells compiler that real declaration is somewhere else.
You can use it in one source file to refer to variable declaration in another file, or in the same file to express that you use previously declared global variable.
So when you declare global variable
int a=5;
and use in function in the same source file, you can add extern int a; in the body of a function to clearly tell that it uses global variable but declaration is not here.
type func(arguments){
extern int a;
.
.
.
And when int a=5 is in another source file you place
extern int a;
in source file you actually want to use global variable a declared in previous source file.
This is about linkage. When you declare a variable extern you give it external linking, saying it's defined with global linkage somewhere else.
In your function you're defining a variable called tmp, but it doesn't have global linkage, it's a local variable. You'd have to define it outside of any function to give it global linkage.
There's also static linkage, which means a variable is global but only to the current compilation unit (source file).
Using the extern keyword you only declare the symbol tmp. Which means the symbols is defined somewhere else and will be resolved at link time.
So if you do not provide a compiled object defining the symbol, the linker gives you some kind of "unresolved symbol" error.
See the following question for more details on Declaration or Definition in C

extern variables in C and their scope

I am trying to understand this code:
#include<stdio.h>
int main()
{
extern int a;
printf("%d\n", a);
return 0;
}
int a=20;
When I run it, the value of a is 20. Yet this should be impossible, since the global variable a is defined at the bottom.
An extern declaration can only be used with variables that are global. It tells the compiler that the global variable is defined elsewhere, and asks the linker to figure it out.
In your code, extern int a refers to the a defined at the bottom of your example. It could have been equally well defined in a different translation unit.
As others have pointed out, the initialization of a takes place before main() is entered.
Not a problem. By declaring the variable as extern you are promising the linker it is defined else where part of current or other source files at global scope.
Initialization of global variables occurs before main() is called.
So even if the initialization a = 20 is located beneath the implementation of main(), it's always executed first, so it can be used at program start (assuming you fittingly declared the variable in scopes where it's to be used using extern int a).

Resources