什么是外部联系和内部联系?

时间:2009-08-31 17:16:23

标签: c++ c++-faq

我想了解外部联系和内部联系及其差异。

我也想知道

的含义
  默认情况下,

const个变量内部链接,除非另有声明为extern

9 个答案:

答案 0 :(得分:268)

由于dudewat said 外部链接意味着整个程序都可以访问符号(函数或全局变量),内部链接意味着它只能在一个{ {3}}。

您可以使用externstatic关键字明确控制符号的关联。如果未指定链接,则非extern符号的默认链接为conststatic符号为const(内部)。

// in namespace 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 foo(); // extern by default
static int bar(); // explicitly static 

请注意,不要使用static进行内部关联,最好使用translation unit,您也可以将class放入其中。匿名命名空间的链接在C ++ 98和C ++ 11之间发生了变化,但主要的是它们无法从其他翻译单元访问。

namespace {
   int i; // external linkage but unreachable from other translation units.
   class invisible_to_others { };
}

答案 1 :(得分:244)

当您编写实现文件(.cpp.cxx等)时,编译器会生成翻译单元。这是您的实现文件中的目标文件以及#include中的所有标题。

内部链接指的是翻译单元范围内仅的所有内容

外部链接是指在特定翻译单元之外存在的内容。换句话说,可通过整个程序访问,这是所有翻译单元(或目标文件)的组合。

答案 2 :(得分:86)

  • 默认情况下,全局变量具有外部链接。通过在另一个文件中提供匹配的 extern 声明,可以将其范围扩展到除包含它之外的文件。
  • 通过在声明前添加关键字 static ,可以将全局变量的范围限制为包含其声明的文件。据说这些变量具有内部联系

请考虑以下示例:

1.cpp

void f(int i);
extern const int max = 10;
int n = 0;
int main()
{
    int a;
    //...
    f(a);
    //...
    f(a);
    //...
}
  1. 函数f的签名将f声明为具有外部链接的函数(默认)。其定义必须在本文件后面或其他翻译单元中提供(见下文)。
  2. max定义为整数常量。常量的默认链接是 internal 。使用关键字 extern 将其链接更改为外部。所以现在可以在其他文件中访问max。
  3. n定义为整数变量。在函数体外定义的变量的默认链接是 external
  4. 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;
    }
    
    1. max声明具有外部链接。 max(带外部链接)的匹配定义必须出现在某个文件中。 (如在1.cpp中)
    2. 声明
    3. n具有外部链接
    4. z 定义内部链接的全局变量。
    5. nCall的定义指定nCall是一个变量,它在函数f()的调用中保留其值。与具有默认自动存储类的局部变量不同,nCall仅在程序开始时初始化一次,而不是每次调用f()时初始化一次。存储类说明符 static 会影响局部变量的生命周期,而不影响其范围。
    6. NB:关键字 static 扮演双重角色。在全局变量的定义中使用时,它指定内部链接。当在局部变量的定义中使用时,它指定变量的生命周期将是程序的持续时间而不是函数的持续时间。

      希望有所帮助!

答案 3 :(得分:25)

就'C'而言(因为静态关键字在'C'和'C ++'之间有不同的含义)

让我们谈谈'C'中的不同范围

范围:基本上我能看到多长时间和多远。

  1. 局部变量:范围仅在函数内部。它驻留在RAM的STACK区域。                 这意味着每次函数调用所有变量                 这是该函数的一部分,包括函数参数                 新鲜创造并在控制失效后被摧毁                 功能。 (因为每次函数返回时都会刷新堆栈)

  2. 静态变量:这是针对文件的范围。它可以在文件中的每个位置访问                 在其中声明。它驻留在RAM的DATA段中。以来                 这只能在文件中访问,因此只能在INTERNAL链接中访问。任何
                    其他文件无法看到此变量。实际上STATIC关键字就是                 我们可以引入某种程度的数据或功能的唯一方式                 藏在'C'

  3. 全局变量:这个范围适用于整个应用程序。每个都可以访问                 申请的地方。全局变量也驻留在DATA段中                 因为它可以在应用程序的每个位置访问,因此                 EXTERNAL Linkage

  4. 默认情况下,所有功能都是全局的。万一,如果你需要 从外部隐藏文件中的一些函数,可以为静态添加前缀 函数的关键字。 : - )

答案 4 :(得分:10)

在讨论这个问题之前,最好先了解术语translation unitprogram和C ++的一些basic concepts(实际上链接是其中一个)。您还必须知道什么是scope

我将强调一些关键点,尤其是以前的答案中缺少的那些。

链接名称的属性,由声明引入。不同的名称可以表示相同的实体(通常是对象或函数)。因此,谈论实体的链接通常是无稽之谈,除非您确定该实体仅由某些特定声明(通常是一个声明)中的唯一名称引用。

注意对象是一个实体,但变量不是。在谈论变量的链接时,实际上是指定实体的名称(由特定声明引入)。名称的链接是三者之一:没有联系,内部联系或外部联系。

不同的翻译单元可以通过标题/源文件共享相同的声明(是的,它是标准的措辞)包含。因此,您可以在不同的翻译单元中引用相同的名称。如果声明的名称具有外部链接,则名称引用的实体的标识也是共享的。如果声明的名称具有内部链接,则不同翻译单元中的相同名称表示不同的实体,但您可以在同一翻译单元的不同范围内引用该实体。如果名称没有链接,则您根本无法从其他范围引用该实体。

(哎呀......我发现我输入的内容有点只是重复the standard wording ...)

还有一些其他令人困惑的问题没有被语言规范所涵盖。

  1. 可见性(名称)。它也是声明名称的属性,但with a meaning different to linkage
  2. Visibility (of a side effect)。这与此主题无关​​。
  3. 可见性(符号)。这个概念可以是used by actual implementations。在这样的实现中,在对象(二进制)代码中具有特定可见性的符号通常是从实体定义映射的目标,该实体定义的名称在源(C ++)代码中具有相同的特定链接。但是,通常不能保证一对一。例如,动态库映像中的符号只能在内部从源代码(包含某些扩展,通常是__attribute____declspec)或编译器选项的内部共享,并且图像是不是整个程序或从翻译单元翻译的目标文件,因此没有标准概念可以准确地描述它。由于符号在C ++中不是一个规范性术语,它只是一个实现细节,即使方言的相关扩展可能已被广泛采用。
  4. 辅助功能。在C ++中,这通常是property of class members or base classes,这也是与主题无关的不同概念。
  5. 全局。 In C++, "global" refers something of global namespace or global namespace scope.后者大致相当于C语言中的文件范围。在C和C ++中,链接与范围无关,尽管范围(如链接)也与某些声明引入的标识符(在C中)或名称(在C ++中)紧密相关。
  6. linkage rule of namespace scope const variable是特殊的(特别是与C语言文件范围中声明的const对象不同,它也具有标识符链接的概念)。由于ODR由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。如果没有const这样的特殊规则,则在标头或源文件(通常是&#34;头文件&中)中使用初始值设定项(例如const)的= xxx变量的最简单声明#34;)由多个翻译单元包含(或由一个翻译单元不止一次包括,但很少)包含在程序中将违反ODR,这使得const变量可以替换某些类似对象的宏。

答案 5 :(得分:5)

我认为Internal and External Linkage in C++给出了一个清晰简洁的解释:

  

翻译单元是指实现(.c / .cpp)文件和所有文件   它包含的头文件(.h / .hpp)。如果是对象或函数里面   这样的翻译单元有内部联系,那就是具体的   符号仅对该转换单元中的链接器可见。如果   一个对象或函数有外部链接,链接器也可以看到它   处理其他翻译单位时。 static关键字,使用时   在全局命名空间中,强制符号具有内部链接。该   extern关键字导致符号具有外部链接。

     

编译器默认符号链接,以便:

     

非const全局变量默认具有外部链接
  Const全局变量默认具有内部链接   默认情况下,函数具有外部链接

答案 6 :(得分:4)

<强>基本上

  • extern linkage变量在所有文件中都可见
  • internal linkage变量在单个文件中可见。

解释:const变量默认在内部链接,除非另有声明为extern

  1. 默认情况下,全局变量为external linkage
  2. 但是,const全局变量为internal linkage
  3. 额外的,extern const全局变量为external linkage
  4. 关于C ++中链接的非常好的材料

    http://www.goldsborough.me/c/c++/linker/2016/03/30/19-34-25-internal_and_external_linkage_in_c++/

答案 7 :(得分:4)

链接确定具有相同名称的标识符是否引用相同的对象,函数或其他实体,即使这些标识符出现在不同的转换单元中也是如此。标识符的链接取决于它的声明方式。 有三种类型的联系:

  1. 内部链接:标识符只能在翻译单元中查看。
  2. 外部链接:可以在其他翻译单元中查看(和引用)标识符。
  3. 无链接:标识符只能在定义它们的范围内看到。 链接不影响范围界定
  4. 仅限C ++ :您还可以在C ++和非C ++代码片段之间建立链接,称为语言链接

    来源:IBM Program Linkage

答案 8 :(得分:0)

在C ++中

文件范围内且未嵌套在类或函数内的任何变量在程序的所有翻译单元中均可见。之所以称为外部链接,是因为链接时该名称对于该翻译单元外部的所有链接器都是可见的。

全局变量和普通函数具有外部链接。

文件范围内的

静态对象或函数名称对于翻译单位而言是本地的。那是 称为内部链接

链接仅指在链接/加载时具有地址的元素。因此,类声明和局部变量没有链接。