What is a concept behind using extern in c/c++? - c++

Sorry for this type of question. But, I am very curious about the keyword extern in C\C++.
while searching for explanation for extern I got to know that extern tell the compiler that the variable or function is already defined in some other file or program.
But if this is a case then why we use extern?
as I tried some codes as follows:
extern int var;
int main(void)
{
var = 10;
return 0;
}
This code is giving me an error message as unresolved external symbol "int var" (?var##3HA).
and if I am using some code like:
extern int var;
int main(void)
{
int var = 10;
return 0;
}
It is not showing any error and gives value same as I have defined in main function.
So, Can any one help me about the behavior of extern?
I am little confused on this.
Please forgive me if it is not a valid question.
Thank you in Advance.

extern is used to refer to a variable in another translation unit ("source file").
For instance, your code in main.c looks like this:
extern int var;
int main(void)
{
var = 10;
return 0;
}
This code contains a declaration for an integer named var, but no definition, because extern explicitly says: "the definition for this is somewhere else"
You could define another source file, say, other.c:
int var = 0;
Then, after you add this new translation unit to your build command, your program will link fine, and the code in both files can operate on the shared var variable.
In the second version, you just override the declaration of the extern var with a local variable in your main function. Since the extern var is not (ODR-)used anymore, the linker does not require it, so your executable can build successfully.

The first version fails since you must also provide a definition of the extern-declared variable, i.e. by linking with some other C file that has
int var;
in its global scope.
The second one succeeds since the int var = 10; line in main() shadows the global declaration; this is generally a bad thing to be doing if you wanted the variable to be extern, i.e. shared among many C files. Of course, such sharing in itself is often quite bad too (see: global variables).

extern is used to indicate that a variable exists in another compilation unit. If you had:
main.cpp
extern int var;
int main(void)
{
var = 10;
return 0;
}
and:
var.cpp
int var;
Then you wouldn't have got the linker error as the linker would have hooked up the use of var in main.cpp with it's decleration in var.cpp
In your second example you've defined an extern int var but you never reference it. The int var = 10 is a completely different int var from the extern one. When they linker runs it notices that you never use the extern int var variable so doesn't bother to search for it.

I would suggest you must clear your understanding of definition and declaration of variable.
extern keyword is used when you want to say that the variable was allocated memory you want only to declare the variable.
When you declare the any variable using extern keyword compiler will try to find the definition of the same variable which can be present before or after declaration.
In the first case you are just declaring the variable not assigning it any memory i.e not defining variable.
you can go through this for better understanding of extern keyword.

If you have declared a global variable, let's say double myvar=5 in file1.cpp and you want to access that variable in file2.cpp, then in your file2.cpp you declare as
extern double myvar;
In C++, each file is called a compilation unit. For the file to be compiled to an object file, you need all variables declared however you do not need to initialize or do an assignment on those variables.
Returning to the example:
File1.cpp: double myvar=5 this is both a declaration and initialization. You can compile file1.cpp to file1.o.
File2.cpp: Assuming that you are using myvar somewhere in file2.cpp and also you want to access the value (maybe after a calculation) in file1.cpp. Therefore, in order to be able to compile file2.cpp into file2.o, you must declare extern double myvar, so that file2.cpp can be compiled. This will please the compiler and leaves the task to linker.
Now that you have compiled these files, you will have object files (translation units) named as (if you are using g++) file1.o and file2.o. Now it is linker's job to link them together and let file2.o to access myvar.

Declaring a variable extern tells the compiler that the actual instance of the variable is somewhere else. If you don't provide it somewhere else, the link stage will fail.
In your second example you don't refer to the extern declared variable at all. You declare a new one in the scope of your main function that shadows the global declaration.

Related

Can we define a variable having extern storage class associated with it?

I was reading about extern storage class from this website:
https://www.geeksforgeeks.org/understanding-extern-keyword-in-c/
and there is this example:
#include "somefile.h"
extern int var;
int main(void)
{
var = 10;
return 0;
}
Supposing that somefile.h has the definition of var
Since we cannot define the variable which is an extern storage class how is it working correctly?
Does it mean that if an extern variable is already defined somewhere in the script and then if I re-define it any further in my code it's going to work?
C Language has methodology :- first Declare it and define it as you know daily use in C. You declare a function and define it somewhere downside.
The Main things is declaring a variable doesn't allocate memory. Memory is only allocated once you define it and in this case var is declare as well defined in somefile.h Memory is allocated via that file only and in this example extern states that this variable is defined somewhere else and Memory is already initialized for it.
[blog]: https://errbits.com/2021/12/16/storage-classes-in-c/ "Storage Classes in C"
And while compile time compiler verify that for same ,if var is already defined in somefile.h it will compile without error since it will check its symbol table to verify if it there.
The keyword extern means external linkage. The below given example gives some basics about extern usage.
someclass.h
#pragma once
extern int var; //this DECLARES an GLOBAL int variable named var with EXTERNAL LINKAGE
In the above someclass.h, we have declared a global int variable named var with External linkage. This means we will be able to use this variable from other files.
someclass.cpp
#include "somefile.h"
int var = 10; //this DEFINES the GLOBAL int variable named var that was DECLARED inside somefile.h with external linkage
In the above file someclass.cpp we have defined the global variable named var that was declared in file somefile.h.
main.cpp
#include "somefile.h"
#include <iostream>
int main(void)
{
std::cout<< var<<std::endl; //prints 10
return 0;
}
In the above file main.cpp we've used(printed on console) the global variable named var without defining it in main.cpp. This is possible because the variable var as i said has external linkage.
The output of the program can be seen here.

C++ - confused about the extern keyword [duplicate]

This question already has answers here:
What is the effect of extern "C" in C++?
(17 answers)
When to use extern in C++
(4 answers)
Closed 8 years ago.
So I am trying to understand it and what it is used for, I get the difference between a declared and defined variable.
I'll try to explain what I am confused at using the examples in the tutorial.
Example 1:
extern int var;
int main(void)
{
var = 10;
return 0;
}
so here I get that you cannot assign var to 10 because no memory was allocated to it.
Example 2:
#include "somefile.h"
extern int var;
int main(void)
{
var = 10;
return 0;
}
I'm lost here. somefile.h would have something like int var = 0;to declare it correct? ut then why would this program declare it again?
Obligatory point #1: this relates to global variables, so the first thing you really need/want to do is not learn how to use them, but how to avoid them. They're much more likely to lead to problems than a solution.
That said, at least in the usual case, you put an extern declaration in a header. You put the definition of the variable in one source file, and you include the header in any other file that needs access to that variable.
For example:
//file1.cpp:
int var;
Then the header that declares the variable:
//file1.h:
extern int var;
Then in one file that needs access to the variable:
#include "file1.h"
int main() {
var = 10; // Yes, this *is* allowed
}
...and in another file that needs access to the variable:
#include "file1.h"
int f() { return var; }
I'll repeat though: this is almost never necessary or desirable. If you're actually using globals very often at all, you're probably doing something wrong (I make it a practice to use a global once a year so I don't forget how, but it's been at least a few years since I used any other than that).
Basically the extern keyword tells the compiler/linker that it should expect the variable to be instantiated and defined elsewhere in the program, for example a library you are linking to or whatever object file "somefile.h" compiles to. Extern lets the compielr and programmer "know" about a variable while letting another piece of code actually manage it.
Here is a good explanation of extern:
https://stackoverflow.com/a/496476/1874323
extern effectively means that somewhere, in all the linked obj files/libraries there exists a variable (in your case) called "var of type int, the compiler doesn't know where, but he'll let the linker find it for you". This keeps the compiler happy.
In your case, you're right, 'int var=1;' must be defined somewhere, actually, in a c\cpp file, not a header (if it was in a header, you wouldn't need to extern it, you could just #include it).
If you extern a variable, but don't define it somewhere, the linker will get unhappy - with an unresolved symbol error (i.e. its saying "you told me to look for a variable called 'var', but I can't find it).
So - theoretically, you should not be able to create an executable with an extern'd variable which isn't defined.

Is there any possible use of using extern variable in a file that is not included in any other file?

I've encountered many examples on the web, that have extern int x in main.c, where the main function lies.
The only use of extern I'm aware of, is to make a declaration in another file, and use it in another file, after defining it.
Like :
a.h : extern int x;
a.c : int x = 5;
main.c :
#include "a.h" // and start using x
The 1st case seems redundant to me.
So,
Is there any possible use of using an extern variable in a file that is not included in any other file?
extern tells the compiler that x exists in a different module and should be linked from elsewhere. Putting it in main.c directly just avoids pulling in a header (which would be included in-line anyways)
Just like in a header, x still needs to exist in another .c module where it isn't defined extern.
extern variable has basically two functions one is to use the variable in the other file and the other is to access global variables as in the following code.
int x=10;
int main()
{
int x=20;
cout<<x; //refers to x=20
if(x==20)
{
extern int x;
cout<<x; //refers to the global x that is x=10
}
}
Of course. Using extern in a file lets you use that variable in that file. It doesn't have to be included anywhere else.
The use of extern causes the object to have external linkage; to
instantiate a template with a object (and not a value or a type), the
object has to have external linkage (at least in C++03). Most objects
defined in namespace scope have global linkage, but const objects don't.
So you have something like:
template <char const* n>
class Toto { /* ... */ };
char const n1[] = "abc";
Toto<n1> t1; // Illegal...
extern char const n2[] = "xyz";
Toto<n2> t2; // Legal...
It's sort of a special case, but it has led me (once or twice) to use
extern in an unnamed namespace in a source file.

When to use extern in C++

I'm reading "Think in C++" and it just introduced the extern declaration. For example:
extern int x;
extern float y;
I think I understand the meaning (declaration without definition), but I wonder when it proves useful.
Can someone provide an example?
This comes in useful when you have global variables. You declare the existence of global variables in a header, so that each source file that includes the header knows about it, but you only need to “define” it once in one of your source files.
To clarify, using extern int x; tells the compiler that an object of type int called x exists somewhere. It's not the compilers job to know where it exists, it just needs to know the type and name so it knows how to use it. Once all of the source files have been compiled, the linker will resolve all of the references of x to the one definition that it finds in one of the compiled source files. For it to work, the definition of the x variable needs to have what's called “external linkage”, which basically means that it needs to be declared outside of a function (at what's usually called “the file scope”) and without the static keyword.
header:
#ifndef HEADER_H
#define HEADER_H
// any source file that includes this will be able to use "global_x"
extern int global_x;
void print_global_x();
#endif
source 1:
#include "header.h"
// since global_x still needs to be defined somewhere,
// we define it (for example) in this source file
int global_x;
int main()
{
//set global_x here:
global_x = 5;
print_global_x();
}
source 2:
#include <iostream>
#include "header.h"
void print_global_x()
{
//print global_x here:
std::cout << global_x << std::endl;
}
It is useful when you share a variable between a few modules. You define it in one module, and use extern in the others.
For example:
in file1.cpp:
int global_int = 1;
in file2.cpp:
extern int global_int;
//in some function
cout << "global_int = " << global_int;
It's all about the linkage.
The previous answers provided good explanations about extern.
But I want to add an important point.
You ask about extern in C++, not in C and I don't know why there is no answer mentioning the case when extern comes with const in C++.
In C++, a const variable has internal linkage by default (not like C).
So this scenario will lead to linking error:
Source 1 :
const int global = 255; //wrong way to make a definition of global const variable in C++
Source 2 :
extern const int global; //declaration
It needs to be like this:
Source 1 :
extern const int global = 255; //a definition of global const variable in C++
Source 2 :
extern const int global; //declaration
This is useful when you want to have a global variable. You define the global variables in some source file, and declare them extern in a header file so that any file that includes that header file will then see the same global variable.

How to access global const variable present in one file to different file

This variable is defined in xyz.cpp
const int i = 10;
The below main() method is written in abc.cpp
void main()
{
cout<<i; //trying to access 'i' from a different .cpp file
}
You need to declare it extern in abc.cpp:
extern const int i;
EDIT: As stated in the comment below, in C++ (unlike C), to give a const variable external linkage, you need to declare it es extern also in xyz.cpp:
extern const int i = 10;
Reference: MSDN
The simplest way is to declare it in a header as const static int i=10; and include that header in all the .cpp that need that constant. This will allow it to be "inlined" by the compiler in every object file, still avoiding ODR violations.
---edit---
Actually, in C++ the static is not required, since const objects have internal linkage by default. But in C, you have to put that static (and in C++ it doesn't hurt).
Why is this better than the extern method? Because:
it's more idiomatic. In C++ you'll always write integral constants in headers as const variables (and that's the very reason why they have internal linkage by default).
it's less typing. You just have to write the const declaration once, then your constants are just a #include away.
it (usually) produces more efficient code. The definition of extern-declared variables cannot be accessed by the compiler when it is producing the current object module, so it cannot optimize it by putting its actual value as an immediate value in the produced machine code, it cannot eliminate branches that cannot be reached with that value of the constant, ... Sure, cross-module optimization ("link time code generation", "whole program optimization", ...) does exist, but at the moment compilers have more advanced optimizers than linkers.
Add the keyword extern in front of it.
Declare it in abc.cpp as:
extern const int i = 10;
const variables in C++ have an internal linkage in C++(unlike C). So to be able to use it in another file you have to explicitly declare it as having external linkage.
Put this global variable into header and #include this header in all .cpp files where you want to use it.
xyz.h:
const int i = 10;
xyz.cpp:
#include "xyz.h"
void main()
{
cout << i;
}
Or if you want to avoid using header for this purpose, you can declare it as extern const int i = 10; in xyz.cpp, but then you have to declare this variable in abc.cpp too, so you should write extern const int i; at the beginning of abc.cpp in order to use it.
The same way as using extern variables.
In the file xyz.cpp:
extern const int i = 333;
In the file abc.cpp:
extern const int i;
cout << i;