Related
This question already has answers here:
How do I use extern to share variables between source files?
(19 answers)
Closed 3 years ago.
There is a code snippet as below,
int var1;
extern int var2;
It is a multiple choice.
The answer is, First statement declares and defines var1, but second statement only declares var2.
But I think it is supposed to be "Both statements only declare variables, don’t define them."
Which one is correct?
This might help. source
Declaration of a variable is for informing to the compiler the
following information: name of the variable, type of value it holds
and the initial value if any it takes. i.e., declaration gives details
about the properties of a variable. Whereas, Definition of a variable
says where the variable gets stored. i.e., memory for the variable is
allocated during the definition of the variable.
In C language definition and declaration for a variable takes place at
the same time. i.e. there is no difference between declaration and
definition. For example, consider the following declaration
int a;
Here, the information such as the variable name: a, and data type:
int, which is sent to the compiler which will be stored in the data
structure known as symbol table. Along with this, a memory of size 2
bytes(depending upon the type of compiler) will be allocated.
Suppose, if we want to only declare variables and not to define it
i.e. we do not want to allocate memory, then the following declaration
can be used
extern int a;
In this example, only the information about the variable is sent and
no memory allocation is done. The above information tells the compiler
that the variable a is declared now while memory for it will be
defined later in the same file or in different file.
The answer depends on several factors.
If these declarations
int var1;
extern int var2;
are block scope declarations then the first declaration is also a definition and the second declaration is just a declaration without a definition. The variable var1 is not initialized that is it has an indeterminate value.
If these declarations are declarations of the file scope then whether the first declaration is a definition is defined by whether the declaration has an external definition.
If the declaration does not have an external definition then this declaration named as tentative definition is a definition and have an implicit initializer equal to 0.
As for the second declaration then again whether it is a definition depends on whether there is an external definition or not. If there is no external definition then the linker can either create the definition or issue an error.
In C a declaration with the file scope is also a definition when either it has an initializer or it is a tentative definition without an external definition.
Actually, the extern keyword extends the visibility of the C variables and C functions.
Declaring vs Defining a variable?
Declaration of a variable/function simply declares that the variable/function exists somewhere in the program but the memory is not allocated for them.
Snippet 1:
extern int var;
int main(void)
{
var = 10;
return 0;
}
Snippet 1 throws an error in compilation. Because var is declared but not defined anywhere. Essentially, the var isn’t allocated any memory. And the program is trying to change the value to 10 of a variable that doesn’t exist at all.
Snippet 2:
#include "somefile.h"
extern int var;
int main(void)
{
var = 10;
return 0;
}
Supposing that "somefile.h" has the definition of var. Snippet 2 will be compiled successfully.
This question already has answers here:
What is the difference between a definition and a declaration?
(27 answers)
Closed 5 years ago.
Can you please someone explain me the flow of below problem,
#include <stdio.h>
int main(){
extern int a;
printf("%d\n",a);
return 0;
}
int a = 20;
and the output is 20. I am not sure where is the variable a getting defined and where is it getting declared?
The variable a is declared and defined as a global variable in the line:
int a = 20;
The extern line just tells the main() function scope that a is defined in another place.
In this case, the use of extern is not really necessary. You could just declare and define a before the main() function, and then main() would be familiar with it.
Usually, you would use extern when you want to use a variable or a function that was defined in another source file (and not just later in the same source file).
The C programming language has been designed to be one-pass, so that the compiler could process each line only once from top to bottom. So considering your program:
#include <stdio.h>
int main(){
extern int a;
printf("%d\n",a);
return 0;
}
int a = 20;
The identifier a is declared twice, and defined once.
Before the 4th line extern int a;, the compiler doesn't know anything about the identifier a. The declaration extern int a; has the block scope within the function main, and it declares the identifier a as an int and that its storage duration is static and linkage is external. So the compiler can write code that access a global identifier by name a as an int variable that could be defined in another module (external linkage). This is what the compiler does on line 5 when it is used in printf.
Finally at line 9, int a = 20; is another declaration and definition. This declares and defines a as a int with static storage duration, and external linkage.
If you'd put the int a = 20; before the main, the declaration extern int a; would be useless, because it doesn't add anything. I tend to put my main and other depending functions last in my source code, so that minimal amount of extra declarations are needed.
extern is syntactically a "storage class" keyword. But there is no such storage class. C has "static storage", "dynamic storage (malloc, etc) and "automatic storage" (local variables, usually represented using a stack).
If an identifier is declared extern inside a block scope, it means that the declaration refers to an external definition. If the entity being declared is an object, then it has static storage, simply because external objects have static storage. It can be a function too; functions aren't said to have storage.
In C, there is a concept called "linkage". Objects declared outside of any function at file scope, and functions, can have "external" or "internal" linkage.
If we have extern in a block scope, as you have in the example program, there can be a prior declaration of the same name at file scope, or in a nested scope, like this:
static int x;
/* ... */
{
extern int x;
}
Here, the inner x refers to the outer x, and, in spite of being "extern", it has internal linkage because of the "static".
In a nutshell, extern usually means "refer to the earlier declaration, and if there isn't one, declare this as an identifier with external linkage".
The word "external" refers to two separate concepts: the aforementioned "external linkage" and also to the meaning "outside of any function", as in "external declaration". Confusingly, "external declarations", like the static int x above, can have "internal linkage"!
In your program, things are correct because the block scope extern declaration of a and the later int a = 20, which are in separate scopes, happen to independently agree with each other.
The int a = 20; is an external declaration, which is also an external definition (because of the initializer). Since in that scope, no prior declaration of a is visible, it gets external linkage.
So, where is a defined? It is defined as an object with external linkage, in the entire translation unit as a whole. That translation unit is what defines a. a is declared in every place of the program where a declaration appears; and its definition is also a declaration. It is declared in main and also in the last line of the translation unit's source code.
A "declaration" is syntax which makes a name known in some scope. It's a concept that is active during the translation of a program. A "definition" is the fact that some object or function is provided in some translation unit. Translated units still provide definitions, but need not retain information about declarations. (Which is why when we make libraries, we provide header files with declarations in them!)
From the point of view of your main function, that function doesn't "care" where a is defined. It has declared a in such a way that if a is used, then an external definition of a, with external linkage, must exist. That definition could come from anywhere: it could be in the same translation unit, or in another translation unit.
When ever you declare a variable as extern then It means that Variable is declared as global and you cannot initialize the variable there.Because no memory is allocated for that variable It is just declared as a Variable
you can define it some where in your code.
Let us take an example ..consider the code
int main()
{
extern int i;
i=10;
printf("%d",sizeof(i));
}
here you get an error that int 'i' is not defined
therefore you need to write it as:
int main()
{
extern int i;
int i=10;
printf("%d",sizeof(i));
}
In case of your code:
This is declaration
extern int a;
This is definition:
int a = 20;
The storage class extern specifies storage duration and linkage of the object the identifier refers to:
The storage duration is set to static, which means the variable is alive for the whole time the program runs. As you declare that variable inside a function scope, this matters in your example, because in function scope, the default storage duration would be automatic.
The linkage is set to external, this just means different translation units of the same program can share the object. It has the side effect that a definition in another (file) scope is acceptable, as shown in your example. This is a logical consequence of the shared nature, you would typically declare a variable with external linkage in all translation units using it, but define it only in one.
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
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).
What is the difference between static and extern in C?
From http://wiki.answers.com/Q/What_is_the_difference_between_static_and_extern:
The static storage class is used to declare an identifier that is a local variable either to a function or a file and that exists and retains its value after control passes from where it was declared. This storage class has a duration that is permanent. A variable declared of this class retains its value from one call of the function to the next. The scope is local. A variable is known only by the function it is declared within or if declared globally in a file, it is known or seen only by the functions within that file. This storage class guarantees that declaration of the variable also initializes the variable to zero or all bits off.
The extern storage class is used to declare a global variable that will be known to the functions in a file and capable of being known to all functions in a program. This storage class has a duration that is permanent. Any variable of this class retains its value until changed by another assignment. The scope is global. A variable can be known or seen by all functions within a program.
static means a variable will be globally known only in this file. extern means a global variable defined in another file will also be known in this file, and is also used for accessing functions defined in other files.
A local variable defined in a function can also be declared as static. This causes the same behaviour as if it was defined as a global variable, but is only visible inside the function. This means you get a local variable whose storage is permanent and thus retain its value between calls to that function.
I'm no C expert so I might be wrong about this, but that's how I've understood static and extern. Hopefully someone more knowledgable will be able to provide you with a better answer.
EDIT: Corrected answer according to comment provided by JeremyP.
You can apply static to both variables and functions. There are two answers that discuss the behaviour of static and extern with respect to variables, but neither really covers functions. This is an attempt to rectify that deficiency.
TL;DR
Use static functions whenever possible.
Only declare external functions in headers.
Use the headers where the functions are defined and where the functions are used.
Don't declare functions inside other functions.
Don't exploit the GCC extension with function definitions nested inside other functions.
External functions
By default, functions in C are visible outside the translation unit (TU — basically the C source file and included headers) in which they are defined. Such functions can be called by name from any code that notifies the compiler that the function exists — usually by a declaration in a header.
For example, the header <stdio.h> makes visible declarations of functions such as printf(), fprintf(), scanf(), fscanf(), fopen(), fclose(), and so on. If a source file includes the header, it can call the functions. When the program is linked, the correct library must be specified to satisfy the function definition. Fortunately, the C compiler automatically provides the library that provides (most of) the functions in the standard C library (and it usually provides a lot more functions than just those). The 'most of' caveat applies because on many systems (Linux, for instance, but not macOS), if you use functions declared in the <math.h> header, you need to link with the maths library ('math' library if you're American), which usually is indicated by the option -lm on the linker command line.
Note that external functions should be declared in headers. Each external function should be declared in one header, but one header may declare many functions. The header should be used both in the TU where each function is defined and in each TU that uses the function. You should never need to write a declaration for a global function in a source file (as opposed to a header file) — there should be a header to declare the function and you should use that header to declare it.
Static functions
As an alternative to generally visible functions, you can make your own functions static. This means that the function cannot be called by name from outside the TU in which it is defined. It is a hidden function.
The primary advantage of static functions is hiding details which the outside world doesn't need to know about. It is a basic but powerful information hiding technique. You also know that if a function is static, you do not need to look for uses of the function outside the current TU, which can greatly simplify the search. However, if the functions are static, there can be multiple TUs which each contain a definition of a function with the same name — each TU has its own function, which may or may not do the same thing as a function with the same name in a different TU.
In my code, I qualify all functions except main() with the keyword static by default — unless there's a header that declares the function. If I subsequently need to use the function from elsewhere, it can be added to the appropriate header and the keyword static removed from its definition.
Declaring functions inside other functions
It is possible, but very inadvisable, to declare a function inside the scope of another function. Such declarations fly in the face of Agile Development maxims such as SPOT (Single Point of Truth) and DRY (Don't Repeat Yourself). They're also a maintenance liability.
However, you can, if you so desire, write code such as:
extern int processor(int x);
int processor(int x)
{
extern int subprocess(int);
int sum = 0;
for (int i = 0; i < x; i++)
sum += subprocess((x + 3) % 7);
return sum;
}
extern int subprocess(int y);
int subprocess(int y)
{
return (y * 13) % 37;
}
The declaration in processor() suffices for it to use subprocess(), but is otherwise unsatisfactory. The extern declaration before the definition is necessary if you use GCC compiler options such as:
$ gcc -O3 -g -std=c11 -Wall -Wextra -Werror -Wmissing-prototypes -Wstrict-prototypes \
> -c process.c
process.c:12:5: error: no previous prototype for ‘subprocess’ [-Werror=missing-prototypes]
int subprocess(int y)
^~~~~~~~~~
cc1: all warnings being treated as errors
$
This is, I find, a good discipline, similar to what C++ enforces. It's another reason I make most functions static, and define the functions before they're used. The alternative is to declare static functions at the top of the file and then define them in whatever order seems appropriate. There are some merits to both techniques; I prefer to avoid the need to declare and define the same function in the file by defining before use.
Note that you cannot declare a static function within another function, and if you attempt to define a function such as subprocess() as a static function, the compiler gives an error:
process.c:12:16: error: static declaration of ‘subprocess’ follows non-static declaration
static int subprocess(int y)
^~~~~~~~~~
process.c:5:20: note: previous declaration of ‘subprocess’ was here
extern int subprocess(int);
^~~~~~~~~~
Since functions that are externally visible should be declared in a header, there is no need to declare them inside a function, so you should never run into this as a problem.
Again, the extern is not necessary in the function declaration inside the function; if omitted, it is assumed. This can lead to unexpected behaviour in novice programs here on SO — you sometimes find a function declaration where a call was intended.
With GCC, the option -Wnested-externs identifies nested extern declarations.
Called by name vs called by pointer
If you have a nervous disposition, stop reading now. This gets hairy!
The 'called by name' comment means that if you have a declaration such as:
extern int function(void);
you can write in your code:
int i = function();
and the compiler and linker will sort things out so that the function is called and the result used. The extern in the declaration of the function is optional but explicit. I normally use it in a header file to match the declaration of those rare global variables — where the extern is not optional but mandatory. Many people disagree with me on this; do as you wish (or must).
Now what about static functions?
Suppose the TU reveal.c defines a function static void hidden_function(int) { … }.
Then, in another TU openness.c, you cannot write :
hidden_function(i);
Only the TU that defines the hidden function can use it directly. However, if there's a function in reveal.c that returns a function pointer to the hidden_function(), then the code openness.c can call that other function (by name) to get a pointer to the hidden function.
reveal1.h
extern void (*(revealer(void)))(int);
Obviously, that's a function that takes no arguments and returns a pointer to a function that takes an int argument and returns no value. No; it isn't pretty. One of the times it makes sense to use typedef on pointers is with pointers to functions (reveal2.h):
typedef void (*HiddenFunctionType)(int);
extern HiddenFunctionType revealer(void);
There: much simpler to understand.
See Is it a good idea to typedef pointers for a general discussion on the subject of typedef and pointers; the short summary is "it isn't a good idea except perhaps with function pointers".
reveal1.c
#include <stdio.h>
#include "reveal1.h"
static void hidden_function(int x)
{
printf("%s:%s(): %d\n", __FILE__, __func__, x);
}
extern void (*(revealer(void)))(int)
{
return hidden_function;
}
Yes, it is legitimate (but very unusual) to define the function with an explicit extern — I very, very seldom do it, but here it emphasizes the role of extern and contrasts it with static. The hidden_function() can be returned by revealer(), and could be called by code inside reveal.c. You can remove the extern without changing the meaning of the program.
openness1.c
#include <stdio.h>
#include "reveal1.h"
int main(void)
{
void (*revelation)(int) = revealer();
printf("%s:%s: %d\n", __FILE__, __func__, __LINE__);
(*revelation)(37);
return 0;
}
This file cannot usefully contain a direct call by name to hidden_function() because it is hidden in the other TU. However, the revealer() function declared in reveal.h can be called by name and it returns a pointer to the hidden function, which can then be used.
reveal2.c
#include <stdio.h>
#include "reveal2.h"
static void hidden_function(int x)
{
printf("%s:%s(): %d\n", __FILE__, __func__, x);
}
extern HiddenFunctionType revealer(void)
{
return hidden_function;
}
openness2.c
#include <stdio.h>
#include "reveal2.h"
int main(void)
{
HiddenFunctionType revelation = revealer();
printf("%s:%s: %d\n", __FILE__, __func__, __LINE__);
(*revelation)(37);
return 0;
}
Sample outputs
Not the most exciting output in the world!
$ openness1
openness1.c:main: 7
reveal1.c:hidden_function(): 37
$ openness2
openness2.c:main: 7
reveal2.c:hidden_function(): 37
$
Both of these modifiers have something to do with memory allocation and linking of your code. The C standard[3] refers to them as storage-class specifiers. Using those allows you to specify when to allocate memory for your object and/or how to link it with the rest of the code. Let’s have look on what exactly is there to specify first.
Linking in C
There are three types of linkage – external, internal and none. Each declared object in your program (i.e. variable or function) has some kind of linkage – usually specified by the circumstances of the declaration. Linkage of an object says how is the object propagated through the whole program. Linkage can be modified by both keywords extern and static .
External Linkage
Objects with external linkage can be seen (and accessed) through the whole program across the modules. Anything you declare at file (or global) scope has external linkage by default. All global variables and all functions have external linkage by default.
Internal Linkage
Variables and functions with internal linkage are accessible only from one compilation unit – the one they were defined in. Objects with internal linkage are private to a single module.
None Linkage
None linkage makes the objects completely private to the scope they were defined in. As the name suggests, no linking is done. This applies to all local variables and function parameters, that are only accessible from within the function body, nowhere else.
Storage duration
Another area affected by these keywords is storage duration, i.e. the lifetime of the object through the program run time. There are two types of storage duration in C – static and automatic.
Objects with static storage duration are initialized on program startup and remain available through the whole runtime. All objects with external and internal linkage have also static storage duration. Automatic storage duration is default for objects with no linkage. These objects are allocated upon entry to the block in which they were defined and removed when the execution of the block is ended. Storage duration can be modified by the keyword static .
Static
There are two different uses of this keyword in the C language. In the first case, static modifies linkage of a variable or function. The ANSI standard states:
If the declaration of an identifier for an object or a function has
file scope and contains the storage-class specifier static , the
identifier has internal linkage.
This means if you use the static keyword on a file level (i.e. not in a function), it will change the object’s linkage to internal, making it private only for the file or more precisely, compilation unit.
/* This is file scope */
int one; /* External linkage. */
static int two; /* Internal linkage. */
/* External linkage. */
int f_one()
{
return one;
}
/* Internal linkage. */
static void f_two()
{
two = 2;
}
int main(void)
{
int three = 0; /* No linkage. */
one = 1;
f_two();
three = f_one() + two;
return 0;
}
The variable and function() will have internal linkage and won’t be visible from any other module.
The other use of static keyword in C is to specify storage duration. The keyword can be used to change automatic storage duration to static. A static variable inside a function is allocated only once (at program startup) and therefore it keeps its value between invocations
#include <stdio.h>
void foo()
{
int a = 10;
static int sa = 10;
a += 5;
sa += 5;
printf("a = %d, sa = %d\n", a, sa);
}
int main()
{
int i;
for (i = 0; i < 10; ++i)
foo();
}
The output will look like this:
a = 15, sa = 15
a = 15, sa = 20
a = 15, sa = 25
a = 15, sa = 30
a = 15, sa = 35
a = 15, sa = 40
a = 15, sa = 45
a = 15, sa = 50
a = 15, sa = 55
a = 15, sa = 60
Extern
The extern keyword denotes, that “this identifier is declared here, but is defined elsewhere”. In other words, you tell the compiler that some variable will be available, but its memory is allocated somewhere else. The thing is, where? Let’s have a look at the difference between declaration and definition of some object first. By declaring a variable, you say what type the variable is and what name it goes by later in your program. For instance you can do the following:
extern int i; /* Declaration. */
extern int i; /* Another declaration. */
The variable virtually doesn’t exist until you define it (i.e. allocate memory for it). The definition of a variable looks like this:
int i = 0; /* Definition. */
You can put as many declaration as you want into your program, but only one definition within one scope. Here is an example that comes from the C standard:
/* definition, external linkage */
int i1 = 1;
/* definition, internal linkage */
static int i2 = 2;
/* tentative definition, external linkage */
int i3;
/* valid tentative definition, refers to previous */
int i1;
/* valid tenative definition, refers to previous */
static int i2;
/* valid tentative definition, refers to previous */
int i3 = 3;
/* refers to previous, whose linkage is external */
extern int i1;
/* refers to previous, whose linkage is internal */
extern int i2;
/* refers to previous, whose linkage is external */
extern int i4;
int main(void) { return 0; }
This will compile without errors.
Summary
Remember that static – the storage-class specifier and static storage duration are two different things. Storage duration is a attribute of objects that in some cases can be modified by static , but the keyword has multiple uses.
Also the extern keyword and external linkage represent two different areas of interest. External linkage is an object attribute saying that it can be accessed from anywhere in the program. The keyword on the other hand denotes, that the object declared is not defined here, but someplace else.
Static
The static variables declared with the keyword static. The static variable initial value is 0. The static variables has block file scope scope.
Extern
A program in C, particularly when it is large, can be broken up into smaller programs. After compiling these, each program file can be joined together to form the large program. These small programs modules that combine together may need some variable that is used by all of them. In C, such a provision can be made by specifying these variables, accessible to all the small program modules, as an external storage class variable. These variables are global to all the small program modules that are formed as separate files. The keyword for declaring such global variables is extern.
Such a global variable is declared like any other variable in one of the program modules while the declaration of these variables is preceded with the keyword extern in all other combining program modules.
The program modules may also be a function or a block. These variables remain in existence as long as the program is in execution and their existence does not terminate upon the exit of a function or block or a program module from its state of execution. These variables are stored in the primary memory and their default value is zero.
Storage classes in C