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 #include
d 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.