extern variables

C

Comp1597

I know this is a standard topic and I've done a fair amount of
googling but I'm still a bit confused by extern variables.

My main text is C++ Primer, 4th edition (Lippman, Lajoie and Moo).

For example, I ran the following program:

// Code below in a source file
#include "SomeHeader.h"
#include <iostream>

int main ()
{
int j = doropi;
std::cout << j;

}

//Code in SomeHeader.h
const int doropi = 9;



The result of the program was that 9 was output. However, what I
expected was a compile error based on the rule (or what I thought was
the rule) that const definitions have file scope and that the way to
use consts from other files was via extern.
My code had no extern and yet I was able to use the const anyway.
This made me question the whole purpose of externs. I didn't need the
extern to fetch a member from another file and yet I thought that was
exactly what extern is for.

What I'd be grateful for is a very simple example of a necessary use
of extern variables. Googling gave me lots of definitions but no
examples.

When I tried to create my own examples, I always found that extern was
unnecessary, and that the program ran fine without this concept.

In case the compiler is relevant, I'm using the latest version of
Visual C++ Express.

Many thanks for your help.
 
N

Neelesh

I know this is a standard topic and I've done a fair amount of
googling but I'm still a bit confused by extern variables.

My main text is C++ Primer, 4th edition (Lippman, Lajoie and Moo).

For example, I ran the following program:

// Code below in a source file
#include "SomeHeader.h"
#include <iostream>

int main ()
{
  int j = doropi;
  std::cout << j;

}

//Code in SomeHeader.h
const int doropi = 9;

The result of the program was that 9 was output.  However, what I
expected was a compile error based on the rule (or what I thought was
the rule) that const definitions have file scope and that the way to
use consts from other files was via extern.
My code had no extern and yet I was able to use the const anyway.
This made me question the whole purpose of externs.  I didn't need the
extern to fetch a member from another file and yet I thought that was
exactly what extern is for.

Two points:

A) You are not actually "fetching" anything from "external file" here.
The "SomeHeader.h" has been "included" in the source file, which means
that the preprocessor will add the entire code from SomeHeader.h
inside your c++ source file, even before the "compiler proper" gets to
see the code. So what "compiler proper" sees is:

const int doropi = 9; //This is added by preprocessor by replacing
#include "SomeHeader.h"

//Preprocessor also replaces #include <iostream> by all its content

int main ()
{
int j = doropi;
std::cout << j;

}

So observe that this file has "doropi" defined as a global variable in
this file itself. There is no need of "extern" anywhere here.

More importantly the following point must be noted:

(B) The keyword "extern" is (typically but not necessarily) used for
declaring variables that are defined in (usually) different
"compilation unit". For example, you may have 1.cc and 2.cc files as:

//1.cc
int i = 10;

//2.cc
extern int i;
int main()
{
int j = i;
}

Now you compile 1.cc and 2.cc separately to create object code. On a
typical linux machine using g++ command line option, one would say:

sh$> g++ -c 1.cc 2.cc
This produces 1.o and 2.o. They can now be linked properly because "i"
used in 2.cc gets its definition from 1.cc

Try doing this:
sh$> g++ 2.cc

Observe what error you get. This error says that you have declared int
i as extern, but haven't given any definition.

Technically, the keyword "extern" indicates that the variable will
have external linkage.
 
T

Tim Love

For example, I ran the following program:

Because of the #include, you're (sort of) copy-pasting SomeHeader.h
into the main file. If you're using g++ you can do
g++ -E Main.cc
to see what the heart of the compiler's given. It's one file.

If you want to see the need for extern, try this.

---
//Code in SomeHeader.h
int doropi = 9;

---
// Code in Main.cc
#include <iostream>
// extern int doropi;
int main ()
{
int j = doropi;
std::cout << j;
}
 
J

James Kanze

I know this is a standard topic and I've done a fair amount of
googling but I'm still a bit confused by extern variables.
My main text is C++ Primer, 4th edition (Lippman, Lajoie and Moo).
For example, I ran the following program:
// Code below in a source file
#include "SomeHeader.h"
#include <iostream>
int main ()
{
int j = doropi;
std::cout << j;
}
//Code in SomeHeader.h
const int doropi = 9;
The result of the program was that 9 was output. However,
what I expected was a compile error based on the rule (or what
I thought was the rule) that const definitions have file scope
and that the way to use consts from other files was via
extern.

There is no "filescope" in C++. And even in C, filescope refers
to the result after preprocessing---translation unit scope would
be a better name.
My code had no extern and yet I was able to use the const
anyway. This made me question the whole purpose of externs.
I didn't need the extern to fetch a member from another file
and yet I thought that was exactly what extern is for.
What I'd be grateful for is a very simple example of a
necessary use of extern variables. Googling gave me lots of
definitions but no examples.

Extern is used when the same entity (variable or function) must
be used in more than one translation unit. Also, a variable
declared extern, but with no initializer, is only a declaration,
not a definition. (You need a declaration everywhere you use
the variable, but there should only be one definition in the
entire program.) Thus, if you want all of your translation
units to access a single "bool shutdownRequested" (to use
something that might reasonably be a "global" variable), you'd
declare:
extern bool shutdownRequested ;
in a header, including it where ever needed, and in a single
source file (which also includes this header):
bool shutdownRequested = false ;
or
extern bool shutdownRequested = false ;

The difference between const and non-const is when neither
extern nor static are specified:
int const c = 42 ;
is the same as:
static int const c = 42 ;
whereas:
int c = 42 ;
is the same as:
extern int c = 42 ;
and
int const c ;
is illegal, whereas:
int c ;
defines an uninitialized variable.
When I tried to create my own examples, I always found that
extern was unnecessary, and that the program ran fine without
this concept.

Try taking the address of the variable in several different
translation units. For const variables, if the extern is
absent, you have a different variable in each translation unit.
 
A

Andrey Tarasevich

For example, I ran the following program:

// Code below in a source file
#include "SomeHeader.h"
#include <iostream>

int main ()
{
int j = doropi;
std::cout << j;

}

//Code in SomeHeader.h
const int doropi = 9;

The result of the program was that 9 was output. However, what I
expected was a compile error based on the rule (or what I thought was
the rule) that const definitions have file scope

There's never been such a rule. The scope of an identifier depends on
the point and the manner of its declaration. It is not tied in any way
to the declaration's being a "const definition" or not.

I don't see why you'd expect a compiler error in your case. You put the
declaration if 'doropi' in an include file and then #include-d it into
your source file before the first use (in 'main'). No problems here.
and that the way to
use consts from other files was via extern.

There is not such thing as "other files" in C++. There's such things as
other _translation_ _units_. In your example you have one and only one
translation unit. So the issue of "using consts from other files
(meaning - other translation units)" simply does not arise here at all.

If you really had to refer to a constant defined in another translation
unit, you'd indeed have to use 'extern'.
My code had no extern and yet I was able to use the const anyway.

Yes. Because you declare, define and use it in the same one translation
unit.
This made me question the whole purpose of externs. I didn't need the
extern to fetch a member from another file and yet I thought that was
exactly what extern is for.

One can say that 'extern' in a non-defining declaration is used for
"fetching" (or "linking to") entities defined in other translation
units. You don't have other translation units in your example, so there
can possibly be any need for such an 'extern' in it.
What I'd be grateful for is a very simple example of a necessary use
of extern variables. Googling gave me lots of definitions but no
examples.

Create a program with _two_ translation units, i.e. _two_ source files.
Put a definition of a variable in one source file:

int variable = 5;

then go to another source file and "fetch" that variable there using
'extern':

#include <iostream>

extern int variable;

int main ()
{
std::cout << variable << std::endl;
}
 
G

gw7rib

There's never been such a rule. The scope of an identifier depends on
the point and the manner of its declaration. It is not tied in any way
to the declaration's being a "const definition" or not.

This looks wrong to me. If one translation unit declares, for example,

int x;

then other translation units can access that variable by using

extern int x;

However, if the first translation unit instead says

const int x = 10;

then other translation units cannot access x at all. If you want x to
be both const, and externally acessible, you have to say

extern const x = 10;

Which I think is the point that the OP is making, and which you appear
to be denying.
 
A

Andrey Tarasevich

This looks wrong to me. If one translation unit declares, for example,

int x;

then other translation units can access that variable by using

extern int x;

However, if the first translation unit instead says

const int x = 10;

then other translation units cannot access x at all. If you want x to
be both const, and externally acessible, you have to say

extern const x = 10;

Which I think is the point that the OP is making, and which you appear
to be denying.

Well, if that's the point the OP is making, then he using incorrect
terminology.

The specific distinction that you just described has absolutely noting
to do with _scope_. The term "scope" in C++ describes name visibility
matters limited to one and only one translation unit.

The proper term for what you are talking about above is "linkage", not
"scope". In C++ by default 'const' objects (defined as in OP's example)
have internal linkage, meaning that

const int x = 10;

is the same as

static const int x = 10;

which is reason you can't link to this object from another translation
unit. For the 'const' object to be "linkable" from other translation
units it needs to be explicitly defined with external linkage as in

extern const int x = 10;

Again, it's _linkage_ that controls this effect, not scope.
 
J

James Kanze

(e-mail address removed) wrote:
There's never been such a rule. The scope of an identifier
depends on the point and the manner of its declaration. It is
not tied in any way to the declaration's being a "const
definition" or not.

The scope, no. But the default linkage, and whether a
declaration is a definition or not, does depend on whether the
object is const.
 
C

Comp1597

Well, if that's the point the OP is making, then he using incorrect
terminology.

The specific distinction that you just described has absolutely noting
to do with _scope_. The term "scope" in C++ describes name visibility
matters limited to one and only one translation unit.

The proper term for what you are talking about above is "linkage", not
"scope". In C++ by default 'const' objects (defined as in OP's example)
have internal linkage, meaning that

   const int x = 10;

is the same as

   static const int x = 10;

which is reason you can't link to this object from another translation
unit. For the 'const' object to be "linkable" from other translation
units it needs to be explicitly defined with external linkage as in

   extern const int x = 10;

Again, it's _linkage_ that controls this effect, not scope.

Many thanks to all the respondents on this thread. The "incorrect
terminology" does not come from me: I was referring to C++ Primer 4th
edition (Lippman, Lajoie and Moo). The assertion that const variables
have "file scope" rather than "global scope" comes from this text.
Hopefully, this will be (or has been) corrected in a later edition.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,062
Latest member
OrderKetozenseACV

Latest Threads

Top