"extern" inside a function? - c++

Well, reading "a bit old" book ("The C programming language", second edition, by Dennis Ritchie), I came a cross the following:
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
and I was like - what?!
"The variable must also be declared in each function that wants to access it". Then, I was shocked one more time:
int max;
/* ... */
int main()
{
extern int max;
/* ... */
}
And one more - what?!
As far as I know (obviously, it's not much and far from enough), extern makes sense only when you define a global variable somewhere and you want to access it through another file (not to define it again).
So:
What's the point of this extern int max inside the main or any other function?
Does the standard really says, that this is a must (that I need to declare, for this example, this max in each function, that will use it?)
Is this the same for C++ (that's why I placed the C++ tag)? This is the first time I see something like this.
Note: this is not the same as What is the use of declaring a static variable as extern inside a function?

Your post surprised me. I had no recollection of that and I've read K&R long ago. I only have the first edition here and it is there too. However, that is not all it says. From the first edition:
The variable must also be declared in each function that wants to
access it; this may be done either by an explicit extern declaration
or implicitly by context.
Note the "implicitly by context." Later in the text:
...if the external definition of a variable occurs in the source file
before its use in a particular function, then there is no need for an
extern declaration in the function. The extern declarations in main,
... are thus redundant. In fact, common practice is to place
definitions of all external variables at the beginning of the source
file, and then omit all extern declarations.
So this is saying that making the extern variable visible can be done inside the function for just that function, or can be done outside any function for all functions following it in the source file. I believe that this is the only place in the book where it is done inside the function, later it uses the familiar once for the file approach.

extern int max inside main or function is saying to the compiler "I am not a local variable inside the main or function, I am the global variable defined elsewhere".
If the global is declared in the same file, not useful. In different file,yes, but not in each function, just declare one time in the head file of the source that use this global variable. This is the same in c++.

The extern is linkage. It means this name, max, is linked to other occurrences of the name, possibly in other files. (That is, when the object modules are linked together to make an executable, all the linked references to this name will be made to refer to the same object.)
The scope of this declaration is the remainder of the function body it is in. That means other functions in this file do not see the name declared by this declaration (unless they declare it themselves).
Scope and linkage are different things.

Another possible reason for extern inside a function is to make sure that no local variable is shadowing the global variable
Without extern:
int max = 33;
int main()
{
int max;
printf("%d", max); // prints indeterminate value (garbage)
}
With extern
int main()
{
extern int max;
int max;
printf("%d", max);
}
Output:
error: redeclaration of ‘max’ with no linkage

Related

Any way I can define and declare an extern object in header?

I'm writing a library which is totally base on templates, so I don't have any cpp files. Now I want to declare an global variable, then I realize I have nowhere to go.
If I simply declared it in header, I will got a "multiple definition" error, if I use extern, I have to create a cpp file to really declare it.
So is there any way I can declare a global variable in header?
P.S. since a static member in a template class can (only) be declared in header, how it works?
You can use macro to for single declaration,
#ifndef __usermacro
#define __usermacro
//Declare global variable
#else
//Declare extern
#endif
As #M.M mentioned, you can use inline declaration if you're on C++17 or above.
Hovever, if that's not the case, you can declare inline function which returns a reference to static variable, just like that:
inline int& getData() {
static int data;
return data;
}
Then, in your .cpp file (as well as in any function body inside your headers) you can simply call it like int& data = getData().
As a side note, if you want to ensure that global object is created only once and is not copied by accident, it could suit you better to use a signleton instead. Global variables are more of a c-style and not really considered a good practice in c++.

How does extern work?

extern is a storage class in C. How exactly does it work? The output of the code given below is 20. How is this the output?
#include <stdio.h>
int main()
{
extern int a;
printf("%d", a);
return 0;
}
int a=20;
It means three things:
The variable has external linkage, and is accessible from anywhere in the program;
It has static storage duration, so its lifetime is that of the program (more or less); and
The declaration is just a declaration, not a definition. The variable must also be defined somewhere (either without the extern, or with an initialiser, or in your case, both).
Specifically, your extern int a; declares that the variable exists, but doesn't define it at that point. At this point, you can use it, and the linker will make sure your use refers to the definition. Then you have the required definition, int a=20; at the end, so all is well.
extern in this case indicates that the symbol a is defined in a different location, such as a different module. So the linker looks for a symbol with the same name in all of the modules that are linked, and if one exists then it sets the address to your local variable a with the address to the externally defined variable. Since you have another a defined outside of your main() function, the a inside your main() function is (basically) the same variable as the one outside.
Since the global a is initialized before the main function executes, the value is 20 by the time you access it.
extern means i declare a variable, just like you implement a function in a source file and declare the prototype in a header to allow other source file to use it.
If you put a global variable in a source file, and use a header to declare it with the extern keyword, each source file including the header will see the variable.
The linker will do the job to tie everything just as it does with functions
extern as a storage class specifier tells the compiler that the object being declared is not a new object, but has storage elsewhere, i.e., is defined elsewhere. You can try this experiment with your code to see how it works. Leave out the keyword extern in your declaration of int a in main(). Then your printf() will print some garbage value, as it would be a new definition of an int with the same identifier, which would hide the global a declared elsewhere.
You use extern to tell the compiler that the variable is defined elsewhere. Without extern in your program compiler would define another variable a (in addition to this in the global scope) in your main() function that would be printed uninitialized.

How to work with variable in namespace

I think I hvae a fundamental misunderstanding of namespace and/or static variable. But I have tried this test code (typed by hand, forgive typos)
test.h:
namespace test{
static int testNum=5;
void setNum(int value);
}
main.cpp:
#include <test.h>
int test::setNum(int value){
testNum=value;
}
int main(){
test::setNum(9);
cout<<test::testNum;
}
when I run this I get the value 5, not 9 as I would have expected. It seems almost as if I have two instances of the testNum variable, but that seems to be the exact opposite of what static should be doing. I'm guessing I've made a mistake in assuming that these features were identical to their java equvilants somehow...
I also get an error stating that testNum is declared multuple times if I remove the static from my declaration of testNum, could someone explain why that is the case as well?
Thank you
First, your misunderstanding has nothing to do with namespaces, it's only about static. For the rest of this answer I'm going to refer to simply testNum because the fact it's in a namespace is irrelevant.
I'm also assuming you have another file, probably called test.cpp, which also includes test.h and defines the setNum function.
When a variable or function at namespace-scope (i.e. not a class member or local to a function) is declared static it means the entity's name is internal to that file. Formally it has "internal linkage", meaning it can't be referred to by name or linked to from other files (it can be indirectly referred to through a pointer or by passing it as an argument to another function.) That means if several files define static int testNum then each file has its own internal variable with that name, distinct from the testNum in every other file (in fact one file could have static int testnum and another could have static double testnum and another static char* testNum, they'd all be distinct and internal to each file.) If you put a definition like that in header then every file that includes the header has its own testNum.
So with static on your variable in a header you have a different variable called testNum in every file that includes test.h. That means if you set testNum in one file and call a function in a different file which uses testNum it refers to a different variable, which just happens to have the same name.
Because of this, declaring non-const static variables in headers is almost always wrong.
Without static you would have a definition of the testNum variable in every file that includes test.h, which is not allowed: every entity must be defined once and once only in your program. The way to solve that is to declare the variable in the header, but not define it, which you do by telling the compiler the variable is extern:
extern int testNum; // N.B. no "= 1" here
That tells the compiler there is a variable with "external linkage" called testNum, so when code refers to testNum it will always mean the same variable (not some name with internal linakge that is a different entity in every file.) After declaring an extern variable it is your responsibility to ensure there is exactly one definition provided somewhere in the program, so in exactly one file (i.e. not in a header that gets included in multiple files) you define it:
int testNum = 1;
static at namespace scope is a misnomer, and shouldn't be used. It
means simply that the entity declared static has internal name binding;
in other words, that the same name in other translation units will refer
to a different entity, and in the case of variable definitions, that
there will be a separate instance of the variable in each translation
unit. It has no effect on lifetime. (All variables declared or
defined at namespace scope have static lifetime.)
static at namespace scope is also deprecated. Don't use it.
With regards to declaring a variable in a header: prefix it with
extern, and not static. If a variable is declared extern, and
there is no initialization, the declaration is not a definition. Of
course, in this case, you must provide a definition somewhere (in a
single source file). Something along the lines of:
extern int testNum = 5;
int testNum = 5;
int testNum; // implicitly initialized with 0.
EDIT:
To clarify somewhat: there is some confusion here between lifetime and
name binding:
an object has a lifetime (auto, static or dynamic—or temporary, or exception), and
a name is bound to an entity; if the name is declared to be a variable, the entity is an object.
Do not confuse the keyword static with static lifetime. (Functions
can be static, but functions have no defined lifetime in C++; they're
just there.)
The rules regarding these are not very orthognal. Basically, with
regards to lifetime:
all variables declared at namespace scope have static lifetime, always,
variables declared at local scope have auto lifetime unless they are declared static, and
variables declared at class scope have the lifetime of the class object which contains them, unless they are declared static.
regards to lifetime.
Objects with static lifetime come into being sometime before main, and
live until after you return from main.
With regards to name binding:
variables declared at namespace scope have external name binding,
unless they are declared static, in which case they have internal
name binding (but this use of static is deprecated), or if they are
const, and are not declared extern,
variables declared at class scope have external name binding, even if they are declared static, and
variables declared at block scope have no binding.
Finally, there is the question of whether a declaration is a definition
or not. If it is a definition, memory is allocated and the object is
(or may be) initialized. If it is not a definition, it simply tells the
compiler that there is a definition somewhere else for the entity
(object) declared in the declaration. In general, a variable
declaration is a definition unless it is declared extern and does
not have an initializer.
You might want to make sure your code actually has problems before you post it asking what's wrong ;)
I copy/pasted and fixed your typos, and manually did the include:
#include <iostream>
using namespace std;
namespace test{
static int testNum=5;
void setNum(int value);
}
void test::setNum(int value){
testNum=value;
}
int main(){
test::setNum(9);
cout<<test::testNum;
}
result:
$ ./a.out
9
What you haven't said is what else is in your program. If you have more than just main.cpp, and include your test.h, then each .cpp file will have its own copy of testNum. If you want them to share then you need all but one to mark it as extern.

Defining extern variable in main() vs. globally

Given the following header file, if 'a' is defined inside the main body, I get a warning "unused variable 'a'" and linker error "undefined reference to 'a'.
header.h:
#ifndef HEADER_H
#define HEADER_H
#include <iostream>
extern int* a;
void f()
{
std::cout<<*a <<std::endl;
return;
}
#endif
main.cpp:
#include "header.h"
int main()
{
int* a = new int(10);
f();
}
However, if 'a' is defined outside of main(), the program links with no errors and f() works as expected (prints 10). Why is this?
Example:
int* a = new int(10);
int main()
{
f();
}
int* a = new int(10);
for this line, if in the main function, you are defining a local variable.
so the extern int* a; only declare a variable, but not define it. then get a linkage error on that symbol
You need to learn about name binding, which determines how two
declarations of the same name are related. When you define a variable
within a function, its name has no linkage; i.e. the entity it refers to
is distinct from any other entity in the program.
More generally: a declaration (and in this sense, a definition is also a
declaration) associates a symbol with an entity—an object (in
which case, the declaration declares a variable), a function, a
reference, a type or anything else you can declare in C++. Whether
different declarations of the same name associate with the same entity
or not is defined by their linkage. C++ recognizes three
different types of linkage:
external linkage, in which the entity can be referred to by declarations in other transation units,
internal linkage, in which the entity can be referred to by other declarations in the same translation unit,
and no linkage, in which the entity cannot be referred to by any other declaration.
Variables declared at block scope (i.e. local variables) have no
linkage, unless they are explicitly declared extern (and a local
variable declared extern cannot be a definition). So the int a in
main declares (and defines) an entity which is independent of any
other a in the program. Variables declared in namespace scope have
external linkage, unless they are declared static, in which case they
have internal linkage; when you define int a at namespace scope, it
has external linkage, and so refers to the same entity you declared with
extern int a in the header.
When you define the variables inside main, it only has scope inside the main function.
The global extern cannot resolve to that. In other words the linker cannot match the extern declared globally to the variable definition inside the main function.
If you define a inside of main, then its scope (visibility) is restricted to main -- an extern declaration will not make it visible anywhere else.
You have to define it at namespace scope (i.e., outside any function) for it to be visible in other translation units.
It's rather annoying to read 4 answers explaining what's wrong, but none explaining how the correct way to fix it. It's probably a safe guess that if the OP doesn't know about scoping he probably also doesn't know about passing variables to a function.
The Problem
You're trying to get at the value of a variable, but the variable is in another function. How can I get at it? Well, the simple answer is, you don't WANT to get at it. You heard me right. The entire reason to use a function is reusability, if you tie your newly created function to another function then you can't use it everywhere. Remember, functions help you be lazy. And a good programmer is a lazy programmer. If you can write a function once and use it in a million places, you're doing it right. ;)
But I still really want to get at the value of that variable
Then you want to use a function parameter to pass the variable to the function.
Functions are named because you can think of them in terms of math. Put variables in, get out useful data after the function has run and done interesting things with those variables. So let's say you have a math function y = f(x), the equivalent of this would be int f(int x) { /*stuff here*/ } then you call it in your main function using int y = f(a) where a is some variable or number.
You want to avoid global variables because they don't always do what you expect (especially if you have a lot of code, it's very easy to accidentally use the same name.)
In your case you want the function to print out the contents of a specific variable, so I think perhaps you're seeking a way use that function with any specific variable. So here's how you do that.
void f(); //hi, I'm a function prototype
void f(int a); //hi, I'm a function prototype that takes a parameter
void f(int a, int b); //hi, I'm a function prototype that takes two parameters (both ints)
void f(int a, ...); //hi, I'm a function prototype that takes an int then any number of extra parameters (this is how printf works.)
So what you really want to do is change your code to something like:
header.h:
#ifndef HEADER_H
#define HEADER_H
#include <iostream>
// extern int* a; // We don't need this
void f(int* a)
{
if (a != NULL) //always, always check to make sure a pointer isn't null (segfaults aren't fun)
std::cout<<*a <<std::endl;
//return; //Don't really need this for a function declared void.
}
#endif
main.cpp:
#include "header.h"
int main()
{
int* a = new int(10);
f(a);
return 0; //main is declared as returning an int, so you should.
}
Functions by value, pointer and reference
So, in your examples I gave I used int rather than int* in your example. The difference between the two is the first one passes the parameter by value. The other by pointer. When you pass a variable to a function a copy of it is ALWAYS made. If you pass it a int, it makes a copy of the int, if you pass it a 4 MB structure it will make a copy of the 4MB structure, if you pass it a pointer to a 4MB structure is will make a copy of the pointer (not the entire structure.) This is important for two reasons:
Performance: Making a copy of a 4MB structure takes some time.
Ability to change contents: If you make a copy of the pointer, the original data is still in the same place and still accessible through the pointer.
What if you want 1 and not 2? Well then you can declare the pointer const. The prototype looks like this: int f(int const* a);
What if you want 2 and not 1? Tough cookies (there no good reason anyway.)
Finally, you can also declare a function to take a reference and not a pointer, the big difference between a reference and a pointer is a reference will not be NULL (and you can't use pointer arithmetic on a reference.) You will want to use either pass by reference or pass by value normally. Needing to pass by pointer is something that I almost never need to do, in my experience it's more of a special case sort of thing.
Pass by reference: int f(int& a);
Pass by const reference: int f(int const& a);
So to sum up:
if you have function that needs parameters:
then:
if you do not need to modify the contents:
then:
if the size of the variable is small:
pass by value: int f(int a);
else if the size of the variable is large:
then:
if the value of the address can be NULL:
pass by const pointer: int f(int const* a);
else:
pass by const reference: int f(int const& a);
else if you do need to modify the contents:
then:
if the value of the address can be NULL:
pass by pointer: int f(int* a);
else:
pass by reference: int f(int& a);
There's some more cases, but these are the main ones, see this website for more details.
When you define the variable in the function main it is valid only in the scope of main. You can define in all function a variable with the name a. But these would be different variables, because each has it's owen scope.
Technically the variable is allocated on the stack while the function is called, therefore each instance has its own storage.

In C, importance and usage of extern storage class specifier [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
What is external linkage and internal linkage in C++
Actually I want to know the importance of extern.
First I wrote some code :
file1.h
extern int i;
file2.c
#include<stdio.h>
#include "file1.h"
int i=20;
int main()
{
printf("%d",i);
return 0;
}
Now my question is that: what is the use of extern variable when I have to define the i in file2.c, declaring in file1.h is in which way useful to me .
sudhanshu
extern allows you to declare a variable (notify the compiler of its existence) without defining it (bringing it into existence). The general rule is that you can declare things as many times as you want, but you can only define them once.
This is useful if, for example, it will be defined elsewhere.
Consider:
file1.c: file2.c:
extern int xyzzy; int xyzzy;
void fn (void) {
xyzzy = 42;
}
When you link together those two functions, there will be one xyzzy, the one defined in file2.c, and that's the one that fn will change.
Now that happens even without the extern. What the extern does is to declare that xyzzy exists to file1.c so that you don't get any I don't know what the blazes "xyzzy" is errors.
In your particular case (if those are your only two files), you don't need it. It's only needed if you had another file that #included file1.h and tried to access i.
It's useful when you have three files:
foo.h
extern int i;
void bar();
a.c:
#include "foo.h"
int i = 6;
int main(){
bar();
}
b.c:
#include "foo.h"
void bar(){
printf("%d\n", i);
}
As you can see, i is shared between both a.c and b.c, not redefined per-file, as would happen without the extern keyword.
The "extern" declaration in C is to indicate that there is an existence of, and the type of, a global variable.
In C mostly each .c file behaves like a seperate module. Hence a variable with "extern" is something that is defined externally to the current module.
It is always a better practise to define the global in one place, and then declare extern references to it in all the other places. When refering to globals provided by any shared library, this is important in order to make sure that your code is referring the correct and common instance of the variable.
From Wikipedia:
When a variable is defined, the compiler allocates memory for that
variable and possibly also initializes its contents to some value.
When a variable is declared, the compiler requires that the variable
be defined elsewhere. The declaration informs the compiler that a
variable by that name and type exists, but the compiler need not
allocate memory for it since it is allocated elsewhere.
Extern is a way to explicitly declare a variable, or to force a
declaration without a definition
If a variable is defined in file 1, in order to utilize the same
variable in another file, it must be declared. Regardless of the
number of files, this variable is only defined once, however, it must
be declared in any file outside of the one containing the definition.
If the program is in several source files, and a variable is defined
in file1 and used in file2 and file3, then extern declarations are
needed in file2 and file3 to connect the occurrences of the variable.
Having extern tells the compiler its a declaration of a variable.
In your example in file1.h imagine what would happen if you didn't specify extern keyword. It will look like there are two definitions of int i. Also, a header file can be included in many .c files. If you compile those .c files and link them, linker would see multiple definitions of the same variable.
extern keyword allows you to say to the compiler ... " Use this variable right now .. I will define and initialize it later ".. i.e " Compile it now .. I will link to its definition later".
You can extern the variable when you define it in some other file and you want to use it in the current context..
The declaration in the header allows you to access the variable from more than one source file, while still only defining it in one place.