I've read Translation units and linkage, and it says:
The concept of linkage applies only to global names. The concept of linkage does not apply to names that are declared within a scope. A scope is specified by a set of enclosing braces such as in function or class definitions.
It says "The concept of linkage applies only to global names" but didn't mention namespace scope. However, I saw namespace scope in some case we have to use extern to make some variables available in other files:
// constants.h
#ifndef CONSTANTS_H
#define CONSTANTS_H
namespace Constants
{
// since the actual variables are inside a namespace,
// the forward declarations need to be inside a namespace as well
extern const double pi;
extern const double avogadro;
extern const double my_gravity;
}
#endif
// constants.cpp
namespace Constants
{
// actual global variables
extern const double pi(3.14159);
extern const double avogadro(6.0221413e23);
extern const double my_gravity(9.2); // m/s^2 -- gravity is light on this planet
}
So what is the official definition? Is it true that linkage concept only apply to global, maybe namespace is part of global?
Namespaces are orthogonal to the distinction between global and local symbols. Namespaces just augment the name of a symbol, they don't change anything else. So, if you have a global variable, and put it inside a namespace it is still global variable, with external linkage.
The exception is when you put something inside an unnamed namespace. In this case, since there is no possible way code in one source file could reference a symbol in an unnamed namespace declared in another file, it is effectively a static symbol, and thus effectively has internal linkage.
Linkage applies to names basic.link/3:
A name is said to have linkage when it might denote the same object, reference, function, type, template, namespace or value as a name introduced by a declaration in another scope:
When a name has external linkage, the entity it denotes can be referred to by names from scopes of other translation units or from other scopes of the same translation unit.
When a name has module linkage, the entity it denotes can be referred to by names from other scopes of the same module unit ([module.unit]) or from scopes of other module units of that same module.
When a name has internal linkage, the entity it denotes can be referred to by names from other scopes in the same translation unit.
When a name has no linkage, the entity it denotes cannot be referred to by names from other scopes.
Names of variables at namespace scope have external linkage unless they meet certain exceptions. basic.link/5.8 For example, non-extern const variables at namespace scope have internal linkage. basic.link/4.2
And yes, global scope is a namespace scope. basic.scope.namespace/4
Here is the relevant section of the spec pertaining to linkage.
And a relevant snippet:
Indicating by default namespaces have external linkage, minus the exceptions given.
Related
Is there a method to declare a namespace with the extern modifier so that the namespace's entire content is externally linked?
You seem to be asking two questions. One regarding external linkage and one regarding the extern specifier.
Regarding the linkage, there is not really a need for such a syntax.
External linkage is already the default at namespace scope, whether in the global namespace or another namespace, except for const non-template non-inline variables and members of anonymous unions. (https://en.cppreference.com/w/cpp/language/storage_duration#internal_linkage)
So the other way around, syntax to make all names in a namespace have internal linkage, is more likely to be required and this is possible with unnamed namespaces
namespace {
//...
}
in which all declared names have internal linkage.
Regarding the extern specifier used to turn a variable definition into just a declaration at namespace scope or to give it external linkage explicitly, I am not aware of any syntax to apply it to a whole namespace. You will have to specify it explicitly on each variable.
In my understanding:
Names declared in an unnamed namespace are added to the enclosing namespace scope and visible in that translation unit.
With the extern specifier, a variable is not automatically defined (default-initialized).
I would expect the following to declare a variable and then define the same variable:
// Declare ::<unnamed>::my_obj with internal linkage and add my_obj to the
// enclosing namespace scope (the global namespace scope).
namespace { extern int my_obj; }
// Expected: Define the variable declared above.
// Actual: Declare and define a new object, ::my_obj.
int my_obj(42);
Instead, it declares two different objects, and warns me about the unused extern int my_obj.
Why doesn't the second my_obj define the first my_obj? Isn't it in scope?
The statement "names declared in an unnamed namespace are added to the enclosing namespace scope" does not mean that members of unnamed namespace become full-fledged members of enclosing namespace. This addition is performed by an implicit using-directive. Such addition makes these names visible to name lookup, but does not make them literal members of the enclosing namespace for other purposes.
The problem you have in your code is the same as the one in the following snippet
namespace A
{
void foo();
}
using namespace A;
void foo() // <- Defines `::foo`, not `A::foo`
{
}
// `A::foo` remains undefined
Despite the fact that we explicitly "added" names from A to the global namespace, it still does not mean that we can define A::foo as a member of global namespace using unqualified name foo.
In order to define A::foo in the above example you still have to refer to it using its qualified name A::foo. With unnamed namespaces this is impossible for obvious reasons.
P.S. Compilers typically implement unnamed namespaces as namespaces with internal compiler-generated names. If you somehow figured out a "hack" to discover that name, technically you'd probably be able to define your my_obj separately by using a qualified name in the definition. But keep in mind that the hidden namespace name is different in different translation units, thus producing a unique my_obj variable in each translation unit.
An unnamed namespace is not a global namespace. It is a specific namespace that is visible only within the translation unit in which it appears.
This cppreference page describes this in more detail.
If you are trying to use a symbol defined in an unnnamed namespace within the same translation unit -- just use it! It's in scope. You don't need an extern
from https://msdn.microsoft.com/en-us/library/2tx32sw2.aspx :
A variable declared with the extern storage-class specifier is a reference to a variable with the same name defined at the external level in any of the source files of the program. The internal extern declaration is used to make the external-level variable definition visible within the block. Unless otherwise declared at the external level, a variable declared with the extern keyword is visible only in the block in which it is declared.
Since the object is declared in a namespace, it must be defined in the same namespace (or rather, if a name is used as a declaration in one namespace and a definition outside that namespace, it refers to two different entities). That it is visible at file scope does not mean that it is a member of that namespace; I think the assertion that —
Names declared in an unnamed namespace are added to the enclosing
namespace scope
— does not mean what you think it does.
The C++11 standard says that An unnamed-namespace-definition behaves as if it were replaced by:
[inline] namespace unique { /* empty body */ }
using namespace unique ;
namespace unique { namespace-body }
(paraphrasing slightly for formatting; the initial "inline" is optional, appearing iff it appears in the unnamed namespace definition).
So, would you expect in this:
namespace a_name {
extern int a;
}
using namespace a_name;
int a = 4;
... that the first mention of a (inside the namespace) would declare the variable and the second define it? (If you would, at least this is consistent. But if you wouldn't, you need to recognize that the standard specifically says that you should get the same behavior from the unnamed namespace).
I don't believe there is any mechanism to declare a member in one namespace and provide the definition for the same member within another namespace, even if the member is visible in the second namespace.
To address comments below:
Yes, extern causes the declaration not to be a definition. I have removed the statement saying that extern had no effect, which was mainly in reference to linkage; that extern does not grant a name within the unnamed namespace external linkage is true, since C++11 (including amendments). Although in C++03 it may have technically granted external linkage, this was only as an attribute of the declaration/definition; the symbol was still not visible outside the translation unit and had no special visibility to the linker. The significance of extern on a member of the unnamed namespace in C++03 then apparently boils down to usability of that member as a constant expression, if it is a const-qualified pointer.
The example that was linked in a comment, following another comment stating that the linkage determined visibility of symbols to the linker which can have consequences, was perhaps intended to demonstrate that (in C++11) symbols in the unnamed namespace can have external linkage, and that non-external linkage pointers cannot be used as as template arguments (i.e. contexts requiring a constant expression) even when declared const. It did indeed fail to compile with GCC, however it compiles successfully with Clang and with the Intel compiler Icc. With any of the three compilers, the symbols declared in the inline namespace are local symbols at the link level (as can be seen using objdump for example) - there is no causal relationship between symbol visibility at the linker level and the error produced.C++11 explicitly makes a statement (3.5) to the effect that
extern-qualified symbols shall have internal linkage if they
reside in the unnamed namespace (specifically: A name having
namespace scope that has not been given internal linkage above has the same linkage as the enclosing namespace if it is the name of - a variable; or ...). Furthermore, const-declared variables with internal linkage should be usable in contexts requiring a constant expression. By reading the standard, there can be little argument that the GCC compiler is behaving incorrectly in this case.
According to the clause 3.5/4 of C++ Standard:
An unnamed namespace or a namespace declared directly or indirectly
within an unnamed namespace has internal linkage.
Simultanously in paragraph 7.3.1.1 we have note 96):
Although entities in an unnamed namespace might have external linkage,
they are effectively qualified by a name unique to their translation
unit and therefore can never be seen from any other translation unit.
How to explicitly make external linkage for name inside unnamed namespace and how to check that linkage is actually external if Standard guaranteed that there is no way to access name defined inside unnamed namespace from another translation unit?
In which cases doing explicit external linkage for name inside unnamed namespace is useful?
Re
” In which cases doing explicit external linkage for name inside unnamed namespace is useful?
The need for external linkage was important for C++03 templates. E.g. a function pointer as template argument had to be a pointer to function of external linkage. For example, the following would not compile with a C++03 compiler:
template< void(*f)() >
void tfunc() { f(); }
#include <stdio.h>
static void g() { printf( "Hello!\n" ); }
int main()
{
tfunc<g>();
}
It compiles fine with a C++11 compiler.
So, with C++11 the anonymous namespace mechanism for having external linkage yet no name conflicts between translation units, is only technically necessary for classes. A class has external linkage. One wouldn't want to have to choose class names that guaranteed did not occur in other translation units.
With C++11 the rules changed not only for template parameters, but for whether things in an anonymous namespace have external linkage or not. With C++03 an anonymous namespace had formally external linkage, possibly unless it is itself within an anonymous namespace (C++03 §3.5/4 last dash + C++03 §7.3.1.1/1). With C++11 an anonymous namespace has formally internal linkage.
This does not matter to the linker, because there's no linking of namespaces, but it matters as a formal device to describe linkage of things:
C++11 §3.5/4:
” An unnamed namespace or a namespace declared directly or indirectly within an unnamed namespace has internal linkage. All other namespaces have external linkage. A name having namespace scope that has not
been given internal linkage above has the same linkage as the enclosing namespace if it is the name of
— a variable; or
— a function; or
— a named class (Clause 9), or an unnamed class defined in a typedef declaration in which the class has the typedef name for linkage purposes (7.1.3); or
— a named enumeration (7.2), or an unnamed enumeration defined in a typedef declaration in which the enumeration has the typedef name for linkage purposes (7.1.3); or
— an enumerator belonging to an enumeration with linkage; or
— a template.
Before going on to your other questions, it's worth noting that this quote from the standard,
” Although entities in an unnamed namespace might have external linkage, they are effectively qualified by a name unique to their translation unit and therefore can never be seen from any other translation unit.
is plain wrong, because an extern "C" entity is visible from other translation units regardless of what namespace it's declared in.
Happily, as I recall, notes are non-normative, i.e. they do not define the language.
Re
” How to explicitly make external linkage for name inside unnamed namespace
just declare a non-const variable, or a function, as extern.
you can declare a non-const variable, or a function, as extern "C", making the linkage extern but at the same time making the namespaces irrelevant as far as linking is concerned: the C language doesn't have them.
namespace {
extern "C" void foo() {} // Extern linkage
} // namespace <anon>
void bar() {} // Also extern linkage, but visible to other TUs.
Re
” how to check that linkage is actually external
well, the linkage affects things like possible conflicts with the One Definition Rule, often abbreviated as the “ODR”, which in C++11 is §3.2.
So, one way to see the linkage in action is to link two object files generated from the above source, as if you had two translation units with that same source code:
C:\my\forums\so\088> g++ -c anon.cpp -o x.o & g++ -c anon.cpp -o y.o
C:\my\forums\so\088> g++ main.cpp x.o y.o
y.o:anon.cpp:(.text+0x0): multiple definition of `foo'
x.o:anon.cpp:(.text+0x0): first defined here
y.o:anon.cpp:(.text+0x7): multiple definition of `bar()'
x.o:anon.cpp:(.text+0x7): first defined here
collect2.exe: error: ld returned 1 exit status
C:\my\forums\so\088> _
The linker complains about multiple definitions of foo, because as with C language binding it appears, as far as the linker is concerned, as a non-inline external linkage member of the global namespace, with two (possibly conflicting) definitions.
How to explicitly make external linkage for name inside unnamed namespace
The only way I can think of is to give it C language linkage, so that its linkage name ignores the namespace qualification:
namespace {
extern void f() { } // has internal linkage despite 'extern'
extern "C" void g() { } // ignores linkage of namespace
}
void (*p)() = f; // ensure 'f' won't be optimized away
(A strict reading of the standard suggests that g should have internal linkage, but that's not what compilers seem to do.)
and how to check that linkage is actually external if Standard guaranteed that there is no way to access name defined inside unnamed namespace from another translation unit?
Typically ELF compilers will implement internal linkage with non-global symbols, so you can compile the code and inspect the object file:
$ g++ -c linkage.cc
$ nm linkage.o
0000000000000000 t _ZN12_GLOBAL__N_11fEv
0000000000000007 T g
0000000000000000 D p
The mangled name of the unnamed namespace can vary between compilers, but demangling it will show:
$ nm -C linkage.o
0000000000000008 t (anonymous namespace)::f()
0000000000000000 T g
0000000000000000 D p
The lowercase t shows that f has local visibility, meaning it can't be linked to from other object files. The uppercase T shows that g has external linkage.
This isn't guaranteed by the standard though, as ELF visibility is not part of the C++ standard, and some compilers implement linkage without using visibility even on ELF platforms, e.g. the EDG compiler produces a global symbol for the same code:
$ nm linkage.o
0000000000000008 T _ZN23_GLOBAL__N__7_link_cc_p1fEv
0000000000000004 C __EDGCPFE__4_9
0000000000000000 T g
0000000000000000 D p
$ nm -C linkage.o
0000000000000008 T (anonymous namespace)::f()
0000000000000004 C __EDGCPFE__4_9
0000000000000000 T g
0000000000000000 D p
So using extern "C" allows you to give a name external linkage even if it appears in an unnamed namespace, but that doesn't make the note correct, because you can refer to that name from other translation units, because it doesn't use the unnamed namespace scope. That suggests to me that the note is simply a leftover from C++03 when entities in unnamed namespaces didn't automatically have internal linkage, and the note should be corrected or removed (and indeed T.C. points out it was already removed by DR 1603).
In which cases doing explicit external linkage for name inside unnamed namespace is useful?
I can't think of any cases where it's useful.
According to the standard[3.5/2]:
When a name has external linkage , the entity it denotes can be
referred to by names from scopes of other translation units or from
other scopes of the same translation unit
and
When a name has internal linkage , the entity it denotes can be
referred to by names from other scopes in the same translation unit.
So basically if you can refer to something in a translation unit different from the one where this something has been defined then it has external linkage, otherwise it has internal linkage. So given the note from the question:
Although entities in an unnamed namespace might have external linkage,
they are effectively qualified by a name unique to their translation
unit and therefore can never be seen from any other translation unit.
We practically have a situation in which we have a name but we don't know it, hence no matter how hard we try we can't refer to it from the different translation unit. And it makes it indistinguishable from the one with internal linkage. So, in my opinion it is just a word juggling — if you can't distinguish one situation from another then they are the same.
In the standard it says that:
When a name has internal linkage , the entity it denotes can be
referred to by names from other scopes in the same translation unit.
and:
A name having namespace scope (3.3.6) has internal linkage if it is
the name of — a variable, function or function template that is
explicitly declared static;
So consider the following code:
#include <stdio.h>
namespace A
{
/* a with internal linkage now.
Entity denoted by a will be referenced from another scope.
This will be main() function scope in my case
*/
static int a=5;
}
int main()
{
int a; //declaring a for unqualified name lookup rules
printf("%d\n",a);//-1216872448
}
I really don't understand the definitions in the standard. What does it mean that:
the entity it denotes can be referred to by names from other scopes in
the same translation unit.
A translation unit usually consists of single source file with all #included files and results in one object file.
A name in namespace scope has by default external linkage, meaning you can refer that name from other translation units (with scope resolution operator or using directive). But if the name is qualified with static, the linkage becomes internal, and the name can not be referred outside the translation unit in which it was defined.
In your example you could access a if the namespace A, the name a and main method is in the same translation unit. But in main, you are declaring another variable a, which hides the a in namespace A. and the a in main is not initialized, so when you print, it actually prints garbage value from a declared in main. If you want to use a from A in main, use like cout<<A::a or use using namespace A; in the source file containing main.
"Translation unit" is the technical term for the chunk of code the compiler processes at one time. Usually this is a .cpp source file and all of the header files it includes.
In practice, this usually means that a translation unit gets compiled into an object file. This object file is not the complete program; it must be "linked" with other object files to make the final program. The "linking" process is simply matching up the various functions and such that are defined in one translation unit and used in one or more others.
For example, your translation unit calls printf, but the definition (machine code) for printf is actually in another translation unit. So the linker has to know 1) where the actual definition of printf is, and 2) where in your code it's called, so it can plug the address of 1) into 2).
printf is an example of something with external linkage; it can be linked to things external to its translation unit. On the flip side, something with internal linkage can only be linked within its translation unit. So, in your example, main can access A::a, which is declared static at the namespace level, but functions defined outside of this translation unit have no way of seeing A::a. This is because the compiler omits the reference to A::a from the link table in the object file.
Finally, what's happening in your example is that the a that main sees is the one it declared inside itself, which is uninitialized. That's why it's printing a garbage value. If you changed main to:
int main()
{
printf("%d\n", A::a);
}
it would print 5.
the entity it denotes can be referred to by names from other scopes in the same translation unit.
For this to make sense, you have to understand the difference between the entity and the name.
In your main function, you are creating a new entity and giving it the name a. The name does not refer to the same entity called a that is in namespace A. It's a different entity not only because it has different linkage, but also because it is in a different namespace.
Local variables have no linkage by default, and so they always specify a new entity. For example
static int a = 5; // a new entity with name `a` that has internal linkage.
int main()
{
int a; // This is a new entity local to function main with no linkage.
// It isn't initialized, so you have undefined behavior if you try to
// access it.
}
In this case, you have two entities, both named a, but they refer to different entities because they are in different scopes with different linkages.
The situation the standard is referring to is like this:
static int a = 5; // A new entity with the name `a` that has internal linkage.
void f()
{
extern int a; // This is a new declaration for the same entity called `a` in
// the global scope.
}
Now you only have one entity, but you still have two names in two different scopes. Those two names are referring to that same single entity.
This is a very tricky point. Because the declaration inside f() has extern, you are saying that you want f's a to refer to an entity that is defined elsewhere. However, since there is already a declaration for a at global scope that is declared static, it makes the a have internal linkage instead of external linkage.
Note that there isn't much practical value for having two names for the same entity with internal linkage since you can always just use the first name instead.
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.