extern storage class variable inside main function [duplicate] - c

This question already has answers here:
How do I use extern to share variables between source files?
(19 answers)
Closed 7 years ago.
I get very confused with the static and extern storage classes. I do not understand what is wrong with the below code snippet. I expect the printf to print the value Zero. The build is failing with the error "Undefined reference to 'i' ". I expect the statement "extern int i" to be a valid C statement. Is it not?
#include<stdio.h>
void main()
{
extern int i;
printf("%d", i);
}

In the function main
extern int i;
is a declaration of i, not definition. It must be defined somewhere.
#include<stdio.h>
int i; //definition
int main()
{
extern int i; //declaration
printf("%d", i);
}
In this example, the declaration is valid, but can be omitted.

When you declare a variable as extern inside a function, the compiler thinks that the variable is defined in some other translation unit. If it's not defined anywhere else, then you will get a linker error saying that the linker can't find the variable.

see when you are using extern storage class in the main then our compiler use to search the declaration of the variable in the perticular location ,here extern stands for compiler that this variable is declared at any location in the program it can be local or outside the scope , if it dont found any declaration then it gives this linking error becoz it is unable to found the variable declaration.

Related

Why does `int x; extern int x;` not compile? [duplicate]

In the following program, I thought that extern int i; will change the following i to refer to the i defined outside main:
#include <stdio.h>
extern int i=1; // warning: 'i' initialized and declared 'extern'
int main()
{
int i=2;
printf("%d\n", i);
extern int i; // error: extern declaration of 'i' follows declaration with no linkage
printf("%d\n", i);
return 0;
}
What is the reason of the "error: extern declaration of 'i' follows declaration with no linkage", where "declaration with no linkage" refers to int i=2;?
After I remove int i=2 in main,
the error is gone,
the warning "warning: 'i' initialized and declared 'extern'" on extern int i=1; also disappear . Why is that?
Thank you for explanations!
#include <stdio.h>
int i=1; // external variable
int main()
{
int i=2; // local variable
printf("%d\n", i); // print local variable i==2
{
extern int i; // point to external variable
printf("%d\n", i); // print external variable i==1
}
return 0;
}
Once you define a variable named i inside your main function, the i at file scope is masked and cannot be accessed (unless you have its address).
When you later add the declaration extern int i, this conflicts with the local variable named i at the same scope since locals can't have external linkage. It does not give you access to the global i.
When you remove the local i, the extern int i declaration matches up with the definition at file scope, so there is no error. As for the warning on extern int i=1;, that did not go away for me on gcc 4.1.2, so that depends on the compiler.
Question: What is the reason of the "error: extern declaration of 'i' follows declaration with no linkage", where "declaration with no linkage" refers to int i=2;?
Answer: We do not need to use the extern keyword here on line 3 when it is a single file in a program and there is no other file in the same program or other location on the same file where the variable int i has its definition. There are two main reasons we can use extern keyword in C:
1. When we want to declare a variable explicitly/globally but without its definition.
2. To make the variable globally visible from any other file in a multi-file program or other location of the same file (see Ihdina's exmaple for this scenario).
Compiling your code on my system I get the following error,
error: extern declaration of 'i' follows non-extern declaration .
which totally makes sense that the compiler detects the extern on line 9 as a duplicate declaration of the same variable int i on line 7.
Question: After I remove int i=2 in main,
the error is gone,
the warning "warning: 'i' initialized and declared 'extern'" on extern int i=1; also disappear . Why is that?
Answer: After removing the int i=2; the error was gone on my system but still I have the following warning message:
warning: 'extern' variable has an initializer [-Wextern-initializer]
Basically my system (Apple LLVM version 8.1.0 (clang-802.0.42)) does not like the explicit initialization with extern keyword. So, you should modify your code as per Ihdina's answer which compiles without error.

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

How are extern variables defined?

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.

Double definition of variable [duplicate]

This question already has answers here:
About Tentative definition
(2 answers)
Closed 9 years ago.
As we know extern declaration of variables can be initialized.
#include<stdio.h>
extern int a=5; //will work as both definition and declaration.
int main()
{
}
Why this programme is compiling and running with no error.
extern int a=5; //will work as both definition and declaration.
int main()
{
}
int a; // isn't it second definition??
C has a concept of a "tentative definition". Most definitions without initializers are "tentative", so an arbitrary number of them are allowed, as long as they don't conflict with each other. At the end of the translation unit, the definition of the variable becomes basically the composite of those (e.g., if one definition says the variable is const and another says it's volatile, the variable will end up as both const and volatile.
A definition with an initializer is never tentative, so only one of them is allowed.

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