“内部联系”是什么意思?

时间:2014-05-14 04:12:13

标签: c++ linkage

在标准中它说:

  

当名称具有内部链接时,它表示的实体可以是   由同一翻译单位中其他范围的名称引用。

  

具有命名空间范围(3.3.6)的名称具有内部链接(如果是)   名称 - 变量,函数或函数模板   显式声明为static;

请考虑以下代码:

#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
}

我真的不明白标准中的定义。这是什么意思:

  

它所代表的实体可以通过其他范围的名称来引用   相同的翻译单位。

3 个答案:

答案 0 :(得分:5)

translation unit通常由包含所有#include d个文件的单个源文件组成,并生成一个目标文件

命名空间范围中的名称默认情况下为外部链接,这意味着您可以从其他翻译单元引用该名称(使用范围解析运算符)或使用指令)。但是,如果名称符合static,则链接将变为 internal ,并且名称不能在定义它的翻译单元之外引用。

在您的示例中,如果名称空间a,名称Aa方法位于相同翻译单元中,您可以访问main 。但是在main中,您声明了另一个变量a,它隐藏了a在命名空间A中。并且main中的a未初始化,因此在打印时,它实际上会打印a中声明的main的垃圾值。如果您要使用aA的{​​{1}},请使用maincout<<A::a在包含using namespace A;的源文件中使用main

答案 1 :(得分:2)

&#34;翻译单位&#34;是编译器一次处理的代码块的技术术语。通常这是一个.cpp源文件及其包含的所有头文件。

实际上,这通常意味着翻译单元被编译成目标文件。该目标文件不是完整的程序;它必须是&#34;链接&#34;与其他目标文件一起制作最终程序。 &#34;链接&#34;过程简单地匹配在一个翻译单元中定义并在一个或多个其他单元中使用的各种功能。

例如,您的翻译单元会调用printf,但printf的定义(机器代码)实际上位于另一个翻译单元中。所以链接器必须知道1)printf的实际定义在哪里,以及2)在你的代码中它被调用,所以它可以将1)的地址插入2)。

printf外部链接的示例; 它可以链接到其翻译单元外部的内容。另一方面,内部链接的内容只能在其翻译单元中链接。因此,在您的示例中,main可以访问在命名空间级别声明为A::a的{​​{1}},但此翻译单元 之外的函数无法访问看到static。这是因为编译器省略了对象文件中链接表对A::a的引用。

最后,您的示例中发生的事情是A::a看到的a是它本身声明的那个,它是未初始化的。这就是它打印垃圾价值的原因。如果您将main更改为:

main

它会打印int main() { printf("%d\n", A::a); }

答案 2 :(得分:0)

  

它所代表的实体可以通过同一翻译单位中其他范围的名称来引用。

为此,您必须了解实体和名称之间的区别。

在您的主要功能中,您正在创建一个新实体并为其指定名称a。该名称不是指名称空间A中名为a的同一实体。它是一个不同的实体,不仅因为它具有不同的链接,还因为它位于不同的名称空间中。

默认情况下,局部变量没有链接,因此它们总是指定一个新实体。例如

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

在这种情况下,您有两个名为a的实体,但它们引用不同的实体,因为它们位于不同的范围内,具有不同的链接。

标准所指的情况是这样的:

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

现在您只有一个实体,但在两个不同的范围内仍有两个名称。这两个名称指的是同一个实体。

这是一个非常棘手的问题。因为f()中的声明有extern,所以您要求f a引用其他地方定义的实体。但是,由于a已声明static在全局范围内声明为a,因此{{1}}具有内部链接而非外部链接。

请注意,对于具有内部链接的同一实体具有两个名称没有多大实际价值,因为您始终只能使用第一个名称。