What does “internal linkage” mean?

2019-05-05 19:52发布

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.

标签: c++ linkage
3条回答
狗以群分
2楼-- · 2019-05-05 19:57

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.

查看更多
男人必须洒脱
3楼-- · 2019-05-05 20:14

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.

查看更多
Bombasti
4楼-- · 2019-05-05 20:22

"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.

查看更多
登录 后发表回答