extern storage class specifier - c++

Section 7.1 of the C++ Standard mentions about 'extern' as a storage class specifier.
N3126 - "The extern specifier can be
applied only to the names of variables
and functions. The extern specifier
cannot be used in the declaration of
class members or function parameters.
For the linkage of a name declared
with an extern specifier, see 3.5. [
Note: The extern keyword can also be
used in explicit-instantiations and
linkage-specifications, but it is not
a storage-class-specifier in such
contexts. —end note ]
I understand about this keyword and it's use in the context of 'linkage specification', but I am unable to get a grasp on the use of 'extern' as a storage specifier.
Don't all 'extern' names have static storage duration?
If Answer to 1 is yes, then why this redundancy? C Compatibility?

extern is a storage class specifier. This is just a fact of the language grammar. extern has a number of effects on the semantics of a program depending on where it is used. It doesn't have the single same effect everywhere. It influences the storage duration and linkage of objects and it also helps determine whether some declarations are also definitions or not.
E.g.:
int a; // Ex1
extern int b; // Ex2
For example, if Ex1 and Ex2 where at global scope then they would both refer to objects with static storage duration and external linkage. In C++, though, the first would be a definition (tentative definition in C) and the second would not. In this example extern has not changed the storage duration or linkage of the declared object.
If Ex1 and Ex2 occurred in a function body then a would refer to an object with automatic storage duration and no linkage but b would refer to an object with external linkage and static storage duration. In this example, extern has affected the meaning of the declaration in both linkage, storage duration and whether or not it is a definition.
Finally, in C++, here is an example where the only effect of extern is changing the linkage from internal to external.
const int c = 5; // static storage duration, internal linkage
extern const int d = 10; // static storage duration, external linkage

It's not really a storage specifier per se. It comes before the variable name much as other storage specifiers do, but all it does is shut the compiler up and tell the linker that it has more work to do.

Extern keyword inform compiler that a extern variable is exists (or function), even if the compiler not able to find it in the file currently being compiled
It forces external linkage

Related

Linkage of identifiers in C++ declared with the specifier extern

In the C Standard (6.2.2 Linkages of identifiers) there is written enough clear
4 For an identifier declared with the storage-class specifier extern
in a scope in which a prior declaration of that identifier is
visible,31) if the prior declaration specifies internal or external
linkage, the linkage of the identifier at the later declaration is the
same as the linkage specified at the prior declaration. If no prior
declaration is visible, or if the prior declaration specifies no
linkage, then the identifier has external linkage.
However I can not find a similar statement in the C++ Standard looking through its section 6.5 Program and linkage.
The question arises due to the following quote from the C++ 17 Standard
3 A name having namespace scope (6.3.6) has internal linkage if it is
the name of
(3.2) — a non-inline variable of non-volatile const-qualified type
that is neither explicitly declared extern nor previously declared to
have external linkage; or
Now consider the following declarations
const int x = 100;
extern const int x;
So it is unclear whether the code is ill-formed or the constant x has internal linkage though it is declared with the specifier extern or the Standard has a defect in the description of this paragraph or I missed the quote in the C++ Standard similar to the quote from the C Standard.
Maybe a defective in basic.link#6, After looking at the dcl.stc#5, it says:
For the linkage of a name declared with an extern specifier, see [basic.link].
However, the rule about declaration declared with a extern specifier is mostly in [basic.link#6], which is:
The name of a function declared in block scope and the name of a variable declared by a block scope extern declaration have linkage. If such a declaration is attached to a named module, the program is ill-formed. If there is a visible declaration of an entity with linkage, ignoring entities declared outside the innermost enclosing namespace scope, such that the block scope declaration would be a (possibly ill-formed) redeclaration if the two declarations appeared in the same declarative region, the block scope declaration declares that same entity and receives the linkage of the previous declaration. If there is more than one such matching entity, the program is ill-formed. Otherwise, if no matching entity is found, the block scope entity receives external linkage. If, within a translation unit, the same entity is declared with both internal and external linkage, the program is ill-formed.
It sounds like that these rules only applies to block scope declaration instead of applying to namespace scope declaration that declared with extern specifier. Except for this paragraph, there is no more rule in section [basic.link] that indicates what the linkage of a name declared by extern specifier. Unlike what says in C standard, the rules apply to whatever declarations declared with extern specifier(regardless of what kind of scopes where the declarations declared).

Are global variables extern by default or is it equivalent to declaring variable with extern in global?

I have gone through following two questions:
static and extern global variables in C and C++
global variable in C are static or not?
Both questions says the two things in different way.
Question 1's Answer:
Global variables are not extern nor static by default on C and C++.
Question 2's Answer:
If you do not specify a storage class (that is, the extern or static keywords), then by default global variables have external linkage
I need to know the following:
Are global variables extern by default in linkage (or) is it equivalent to declaring variables by specifying extern storage class?
Are global variables static by default in scope (or) is it equivalent to declaring variables by specifying static storage class?
Is there any difference with C or C++? Can anyone please clarify?
is global variables are extern by default in linkage (or) it is equivalent to declaring variable by specifying extern storage class?
The default storage duration, scope and linkage of variables declared outside any block, at the outer most level, have static storage duration, file scope and external linkage. C11 standard says that:
6.2.1 Scopes of identifiers (p4):
[...] If the declarator or type specifier that declares the identifier appears outside of any block or list of parameters, the identifier has file scope, which terminates at the end of the translation unit. [...]
6.2.2 Linkages of identifiers (p5):
[...] If the declaration of an identifier for an object has file scope and no storage-class specifier, its linkage is external.
6.2.4 Storage durations of objects (p3):
An object whose identifier is declared without the storage-class specifier
_Thread_local, and either with external or internal linkage or with the storage-class specifier static, has static storage duration.
So, if x is global
int x;
then its storage duration, scope and linkage is equivalent to x in
extern int x;
is global variables are static by default in scope (or) it is equivalent to declaring variable by specifying static storage class?
No. As I stated above that its duration is static and it has file scope.
If there is any c or c++ difference please clarify?
No difference. Rule is same in both languages.
is global variables are extern by default in linkage (or) it is equivalent to declaring variable by specifying extern storage class?
Unless otherwise specified, they have external linkage (except in C++, where they have internal linkage if they're constant).
The first answer you link to is saying that it's not equivalent to declaring it extern (which makes it a pure declaration, not a definition); not that it doesn't have external linkage.
is global variables are static by default in scope (or) it is equivalent to declaring variable by specifying static storage class?
In C++, they have internal linkage (as if declared static) if they are constant, external linkage otherwise. In C, they always have external linkage.
If there is any c or c++ difference please clarify?
As mentioned above, the default is always external linkage in C, while in C++ it's internal for constant variables.
Verified by using gcc version9.3.0:
Global variables are extern by default.

Can a variable be declared both static and extern?

Why the following doesn't compile?
...
extern int i;
static int i;
...
but if you reverse the order, it compiles fine.
...
static int i;
extern int i;
...
What is going on here?
This is specifically given as an example in the C++ standard when it's discussing the intricacies of declaring external or internal linkage. It's in section 7.1.1.7, which has this exert:
static int b ; // b has internal linkage
extern int b ; // b still has internal linkage
extern int d ; // d has external linkage
static int d ; // error: inconsistent linkage
Section 3.5.6 discusses how extern should behave in this case.
What's happening is this: static int i (in this case) is a definition, where the static indicates that i has internal linkage. When extern occurs after the static the compiler sees that the symbol already exists and accepts that it already has internal linkage and carries on. Which is why your second example compiles.
The extern on the other hand is a declaration, it implicitly states that the symbol has external linkage but doesn't actually create anything. Since there's no i in your first example the compiler registers i as having external linkage but when it gets to your static it finds the incompatible statement that it has internal linkage and gives an error.
In other words it's because declarations are 'softer' than definitions. For example, you could declare the same thing multiple times without error, but you can only define it once.
Whether this is the same in C, I do not know (but netcoder's answer below informs us that the C standard contains the same requirement).
For C, quoting the standard, in C11 6.2.2: Linkage of identifiers:
3) If the declaration of a file scope identifier for an object or a function contains the storage-class specifier static, the identifier has internal linkage.
4) For an identifier declared with the storage-class specifier extern in a scope in which a prior declaration of that identifier is visible, if the prior declaration specifies internal or external linkage, the linkage of the identifier at the later declaration is the same as the
linkage specified at the prior declaration. If no prior declaration is visible, or if the prior declaration specifies no linkage, then the identifier has external linkage.
(emphasis-mine)
That explains the second example (i will have internal linkage). As for the first one, I'm pretty sure it's undefined behavior:
7) If, within a translation unit, the same identifier appears with both internal and external linkage, the behavior is undefined.
...because extern appears before the identifier is declared with internal linkage, 6.2.2/4 does not apply. As such, i has both internal and external linkage, so it's UB.
If the compiler issues a diagnostic, well lucky you I guess. It could compile both without errors and still be compliant to the standard.
C++:
7.1.1 Storage class specifiers [dcl.stc]
7) A name declared in a namespace scope without a storage-class-specifier has external linkage unless it has
internal linkage because of a previous declaration and provided it is not declared const. Objects declared
const and not explicitly declared extern have internal linkage.
So, the first one attempts to first gives i external linkage, and internal afterwards.
The second one gives it internal linkage first, and the second line doesn't attempt to give it external linkage because it was previously declared as internal.
8) The linkages implied by successive declarations for a given entity shall agree. That is, within a given scope,
each declaration declaring the same variable name or the same overloading of a function name shall imply
the same linkage. Each function in a given set of overloaded functions can have a different linkage, however.
[ Example:
[...]
static int b; // b has internal linkage
extern int b; // b still has internal linkage
[...]
extern int d; // d has external linkage
static int d; // error: inconsistent linkage
[...]
In Microsoft Visual Studio, both versions compile just fine.
On Gnu C++ you get an error.
I'm not sure which compiler is "correct". Either way, having both lines doesn't make much sense.
extern int i means that the integer i is defined in some other module (object file or library). This is a declaration. The compiler will not allocate storage the i in this object, but it will recognize the variable when you are using it somewhere else in the program.
int i tells the compiler to allocate storage for i. This is a definition. If other C++ (or C) files have int i, the linker will complain, that int i is defined twice.
static int i is similar to the above, with the extra functionality that i is local. It cannot be accessed from other module, even if they declare extern int i. People are using the keyword static (in this context) to keep i localize.
Hence having i both declared as being defined somewhere else, AND defined as static within the module seems like an error. Visual Studio is silent about it, and g++ is silent only in a specific order, but either way you just shouldn't have both lines in the same source code.

What is external linkage and internal linkage?

I want to understand the external linkage and internal linkage and their difference.
I also want to know the meaning of
const variables internally link by default unless otherwise declared as extern.
When you write an implementation file (.cpp, .cxx, etc) your compiler generates a translation unit. This is the source file from your implementation plus all the headers you #included in it.
Internal linkage refers to everything only in scope of a translation unit.
External linkage refers to things that exist beyond a particular translation unit. In other words, accessible through the whole program, which is the combination of all translation units (or object files).
As dudewat said external linkage means the symbol (function or global variable) is accessible throughout your program and internal linkage means that it is only accessible in one translation unit.
You can explicitly control the linkage of a symbol by using the extern and static keywords. If the linkage is not specified then the default linkage is extern (external linkage) for non-const symbols and static (internal linkage) for const symbols.
// In namespace scope or global scope.
int i; // extern by default
const int ci; // static by default
extern const int eci; // explicitly extern
static int si; // explicitly static
// The same goes for functions (but there are no const functions).
int f(); // extern by default
static int sf(); // explicitly static
Note that instead of using static (internal linkage), it is better to use anonymous namespaces into which you can also put classes. Though they allow extern linkage, anonymous namespaces are unreachable from other translation units, making linkage effectively static.
namespace {
int i; // extern by default but unreachable from other translation units
class C; // extern by default but unreachable from other translation units
}
A global variable has external linkage by default. Its scope can be extended to files other than containing it by giving a matching extern declaration in the other file.
The scope of a global variable can be restricted to the file containing its declaration by prefixing the declaration with the keyword static. Such variables are said to have internal linkage.
Consider following example:
1.cpp
void f(int i);
extern const int max = 10;
int n = 0;
int main()
{
int a;
//...
f(a);
//...
f(a);
//...
}
The signature of function f declares f as a function with external linkage (default). Its definition must be provided later in this file or in other translation unit (given below).
max is defined as an integer constant. The default linkage for constants is internal. Its linkage is changed to external with the keyword extern. So now max can be accessed in other files.
n is defined as an integer variable. The default linkage for variables defined outside function bodies is external.
2.cpp
#include <iostream>
using namespace std;
extern const int max;
extern int n;
static float z = 0.0;
void f(int i)
{
static int nCall = 0;
int a;
//...
nCall++;
n++;
//...
a = max * z;
//...
cout << "f() called " << nCall << " times." << endl;
}
max is declared to have external linkage. A matching definition for max (with external linkage) must appear in some file. (As in 1.cpp)
n is declared to have external linkage.
z is defined as a global variable with internal linkage.
The definition of nCall specifies nCall to be a variable that retains its value across calls to function f(). Unlike local variables with the default auto storage class, nCall will be initialized only once at the first invocation of f(). The storage class specifier static affects the lifetime of the local variable and not its scope.
NB: The keyword static plays a double role. When used in the definitions of global variables, it specifies internal linkage. When used in the definitions of the local variables, it specifies that the lifetime of the variable is going to be the duration of the program instead of being the duration of the function.
In terms of 'C' (Because static keyword has different meaning between 'C' & 'C++')
Lets talk about different scope in 'C'
SCOPE: It is basically how long can I see something and how far.
Local variable : Scope is only inside a function. It resides in the STACK area of RAM.
Which means that every time a function gets called all the variables
that are the part of that function, including function arguments are
freshly created and are destroyed once the control goes out of the
function. (Because the stack is flushed every time function returns)
Static variable: Scope of this is for a file. It is accessible every where in the file
in which it is declared. It resides in the DATA segment of RAM. Since
this can only be accessed inside a file and hence INTERNAL linkage. Any
other files cannot see this variable. In fact STATIC keyword is the
only way in which we can introduce some level of data or function
hiding in 'C'
Global variable: Scope of this is for an entire application. It is accessible form every
where of the application. Global variables also resides in DATA segment
Since it can be accessed every where in the application and hence
EXTERNAL Linkage
By default all functions are global. In case, if you need to
hide some functions in a file from outside, you can prefix the static
keyword to the function. :-)
Before talking about the question, it is better to know the term translation unit, program and some basic concepts of C++ (actually linkage is one of them in general) precisely. You will also have to know what is a scope.
I will emphasize some key points, esp. those missing in previous answers.
Linkage is a property of a name, which is introduced by a declaration. Different names can denote same entity (typically, an object or a function). So talking about linkage of an entity is usually nonsense, unless you are sure that the entity will only be referred by the unique name from some specific declarations (usually one declaration, though).
Note an object is an entity, but a variable is not. While talking about the linkage of a variable, actually the name of the denoted entity (which is introduced by a specific declaration) is concerned. The linkage of the name is in one of the three: no linkage, internal linkage or external linkage.
Different translation units can share the same declaration by header/source file (yes, it is the standard's wording) inclusion. So you may refer the same name in different translation units. If the name declared has external linkage, the identity of the entity referred by the name is also shared. If the name declared has internal linkage, the same name in different translation units denotes different entities, but you can refer the entity in different scopes of the same translation unit. If the name has no linkage, you simply cannot refer the entity from other scopes.
(Oops... I found what I have typed was somewhat just repeating the standard wording ...)
There are also some other confusing points which are not covered by the language specification.
Visibility (of a name). It is also a property of declared name, but with a meaning different to linkage.
Visibility (of a side effect). This is not related to this topic.
Visibility (of a symbol). This notion can be used by actual implementations. In such implementations, a symbol with specific visibility in object (binary) code is usually the target mapped from the entity definition whose names having the same specific linkage in the source (C++) code. However, it is usually not guaranteed one-to-one. For example, a symbol in a dynamic library image can be specified only shared in that image internally from source code (involved with some extensions, typically, __attribute__ or __declspec) or compiler options, and the image is not the whole program or the object file translated from a translation unit, thus no standard concept can describe it accurately. Since symbol is not a normative term in C++, it is only an implementation detail, even though the related extensions of dialects may have been widely adopted.
Accessibility. In C++, this is usually about property of class members or base classes, which is again a different concept unrelated to the topic.
Global. In C++, "global" refers something of global namespace or global namespace scope. The latter is roughly equivalent to file scope in the C language. Both in C and C++, the linkage has nothing to do with scope, although scope (like linkage) is also tightly concerned with an identifier (in C) or a name (in C++) introduced by some declaration.
The linkage rule of namespace scope const variable is something special (and particularly different to the const object declared in file scope in C language which also has the concept of linkage of identifiers). Since ODR is enforced by C++, it is important to keep no more than one definition of the same variable or function occurred in the whole program except for inline functions. If there is no such special rule of const, a simplest declaration of const variable with initializers (e.g. = xxx) in a header or a source file (often a "header file") included by multiple translation units (or included by one translation unit more than once, though rarely) in a program will violate ODR, which makes to use const variable as replacement of some object-like macros impossible.
I think Internal and External Linkage in C++ gives a clear and concise explanation:
A translation unit refers to an implementation (.c/.cpp) file and all
header (.h/.hpp) files it includes. If an object or function inside
such a translation unit has internal linkage, then that specific
symbol is only visible to the linker within that translation unit. If
an object or function has external linkage, the linker can also see it
when processing other translation units. The static keyword, when used
in the global namespace, forces a symbol to have internal linkage. The
extern keyword results in a symbol having external linkage.
The compiler defaults the linkage of symbols such that:
Non-const global variables have external linkage by default
Const global variables have internal linkage by default
Functions have external linkage by default
Basically
extern linkage variable is visible in all files
internal linkage variable is visible in single file.
Explain: const variables internally link by default unless otherwise declared as extern
by default, global variable is external linkage
but, const global variable is internal linkage
extra, extern const global variable is external linkage
A pretty good material about linkage in C++
http://www.goldsborough.me/c/c++/linker/2016/03/30/19-34-25-internal_and_external_linkage_in_c++/
Linkage determines whether identifiers that have identical names refer to the same object, function, or other entity, even if those identifiers appear in different translation units. The linkage of an identifier depends on how it was declared.
There are three types of linkages:
Internal linkage : identifiers can only be seen within a translation unit.
External linkage : identifiers can be seen (and referred to) in other translation units.
No linkage : identifiers can only be seen in the scope in which they are defined.
Linkage does not affect scoping
C++ only : You can also have linkage between C++ and non-C++ code fragments, which is called language linkage.
Source :IBM Program Linkage
In C++
Any variable at file scope and that is not nested inside a class or function, is visible throughout all translation units in a program. This is called external linkage because at link time the name is visible to the linker everywhere, external to that translation unit.
Global variables and ordinary functions have external linkage.
Static object or function name at file scope is local to translation unit. That is
called as Internal Linkage
Linkage refers only to elements that have addresses at link/load time; thus, class declarations and local variables have no linkage.

Why does const imply internal linkage in C++, when it doesn't in C?

See subject. What were they thinking?
UPDATE: Changed from "static" to "internal linkage" to save confusion.
To give an example... Putting the following in a file:
const int var_a = 1;
int var_b = 1;
...and compiling with g++ -c test.cpp only exports var_b.
I believe you mean
Why does const imply internal linkage in C++
It's true that if you declare a const object at namespace scope, then it has internal linkage.
Appendix C (C++11, C.1.2) gives the rationale
Change: A name of file scope that is explicitly declared const, and not explicitly declared extern, has internal linkage, while in C it would have external linkage
Rationale: Because const objects can be used as compile-time values in C++, this feature urges programmers to provide explicit initializer values for each const. This feature allows the user to put const objects in header files that are included in many compilation units.
As litb said, const objects have internal linkage in C++. This is because they are intended to be used like this:
// a.cpp
const int BUFSIZE = 100;
char abuf[BUFSIZE];
// b.cpp
const int BUFSIZE = 256
int bbuf[BUFSIZE];
Const and static are orthogonal concepts in both C and C++.
The const keyword tells the compiler to disallow the variable from appearing as the lvalue of any expression - essentially making it read-only.
In C, the static keyword has several uses depending on what it is applied to. When applied to a variable of a function, it indicates that the variable is not stored in the local scope of a function, but is accessible across invocations of it. When applied to a global variable or function, it becomes accessible only to a particular file - in other words, it is accessible only within the compilation unit (unless declared extern).
In C++, the static keyword can be used within a class definition, to make a variable or functions shared across all instances of the class, rather than being local to each instance. Furthermore, a static class function in C++ can only access static variables of that class (or classes it has access to). Now, in C++ const does give members internal linkage to the compilation unit unless they are explicitly declared extern - this may be what you are referring it. This allows compile-time constants to be shared across unit through the use of header files. Keep in mind, though, that the members are not really static - rather the constant is compiled into each location where it is referenced.
In C & C++ the term static has multiple meanings (it can govern linkage and storage)
You'll have to read Stroustrup's D&E to appreciate his rationale - but when you declare a variable to be const at namespace scope it automatically has internal linkage - whereas in C you have to declare it static to force it to have internal linkage.
Of course in C++, the use of static to control linkage has been deprecated, anonymous namespaces can be used to simulate internal linkage in C++.
const variables in C++ were supposed to replace preprocessor constants - and since preprocessor constants are only visible in files that define them, similarly, const automatically makes the variable visible only in the file that defines it.
Those concepts are orthogonal and should not be thought as the same thing.
Constness is an access propriety : it tells only if your variable should be read-only (const) or write-read (non-const).
Staticity is a life-time (and technically memory localization) property : it tells if the variable will be global in the scope of a class (when in a class) or a translation unit (when used with a global variable defined in a cpp).
It doesn't, and the most obvious example is that if you have a const member variable (which is initialised by the constructor, of course), it is not shared by all objects of that class, but individual to each.
class A {
public:
A(int newx) : x(newx);
private
int x;
}
litb gives the best answer, above.
It doesn't. Writing the following:
const int i = 0;
doesn't make i static (in either C or C++).