401

我想了解外部联系和内部联系以及它们的区别。

我也想知道是什么意思

const默认情况下,变量在内部链接,除非另外声明为extern.

4

9 回答 9

345

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

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

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

于 2009-08-31T17:59:03.887 回答
332

正如dudewat 所说, 外部链接意味着符号(函数或全局变量)可以在整个程序中访问,而内部链接意味着它只能在一个翻译单元中访问。

extern您可以使用andstatic关键字显式控制符号的链接。如果未指定链接,则默认链接是extern(外部链接)非const符号和static(内部链接)const符号。

// 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 

请注意,与其使用static(内部链接),不如使用匿名命名空间,您也可以将classes 放入其中。尽管它们允许extern链接,但匿名名称空间无法从其他翻译单元访问,从而有效地 static进行链接。

namespace {
  int i; // extern by default but unreachable from other translation units
  class C; // extern by default but unreachable from other translation units
}
于 2009-08-31T18:37:43.510 回答
122
  • 全局变量默认具有外部链接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

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. n被声明为具有外部链接
  3. z定义为具有内部链接的全局变量。
  4. 的定义nCall指定nCall为一个变量,该变量在对 function 的调用中保留其值f()。与具有默认自动存储类的局部变量不同,nCall它将仅在程序启动时初始化一次,而不是在每次调用f(). 存储类说明符static影响局部变量的生命周期,而不是其范围。

注意:关键字static起到双重作用。在全局变量的定义中使用时,它指定了内部链接。当用于局部变量的定义时,它指定变量的生命周期将是程序的持续时间,而不是函数的持续时间。

希望有帮助!

于 2010-02-26T19:21:59.650 回答
31

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

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

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

  1. 局部变量:范围仅在函数内部。它位于 RAM 的堆栈区域。这意味着每次调用函数时,作为该函数一部分的所有变量,包括函数参数都是新创建的,并且一旦控制离开函数就会被销毁。(因为每次函数返回时都会刷新堆栈)

  2. 静态变量:这个范围是一个文件。它在声明它的文件
    中的任何地方都可以访问。它位于 RAM 的 DATA 段中。因为这只能在文件内部访问,因此只能在内部链接中访问。任何
    其他文件都看不到此变量。事实上 STATIC 关键字是我们可以引入某种级别的数据或
    隐藏在“C”中的函数的唯一方法

  3. 全局变量:此范围适用于整个应用程序。它可以从应用程序的任何地方访问。全局变量也驻留在 DATA 段中,因为它可以在应用程序中的任何地方访问,因此可以访问外部链接

默认情况下,所有函数都是全局的。如果您需要从外部隐藏文件中的某些函数,您可以在函数前面加上 static 关键字。:-)

于 2010-08-12T11:46:26.137 回答
18

在说问题之前,最好准确地了解翻译单元程序和C++的一些基本概念(实际上链接是其中之一)。您还必须知道什么是范围

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

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

请注意,对象是实体,但变量不是。在谈论变量的链接时,实际上涉及到表示实体的名称(由特定声明引入)。名称的联动是三联之一:无联动、内联动或外联动。

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

(糟糕……我发现我输入的内容有点重复标准措辞……)

语言规范中还没有涵盖其他一些令人困惑的点。

  1. 可见性(名称)。它也是声明名称的属性,但与链接的含义不同
  2. 可见性(副作用)。这与本主题无关。
  3. (符号的)可见性。这个概念可以被实际实现使用。在这样的实现中,在对象(二进制)代码中具有特定可见性的符号通常是从实体定义映射的目标,其名称在源(C++)代码中具有相同的特定链接。但是,通常不能保证一对一。例如,动态库图像中的符号可以指定仅在该图像内部从源代码共享(通常涉及一些扩展,__attribute____declspec) 或编译器选项,并且图像不是整个程序或从翻译单元翻译的目标文件,因此没有标准概念可以准确地描述它。由于符号不是 C++ 中的规范术语,它只是一个实现细节,尽管方言的相关扩展可能已被广泛采用。
  4. 可访问性。在 C++ 中,这通常与类成员或基类的属性有关,这又是一个与主题无关的不同概念。
  5. 全球的。在 C++ 中,“全局”指的是全局命名空间或全局命名空间范围。后者大致相当于C 语言中的文件作用域。在 C 和 C++ 中,链接与范围无关,尽管范围(如链接)也与某个声明引入的标识符(在 C 中)或名称(在 C++ 中)密切相关。

命名空间范围const变量的链接规则有些特殊(特别不同于constC语言文件范围内声明的对象,它也有标识符链接的概念)。由于ODR由 C++ 强制执行,因此在整个程序中保留不超过一个相同变量或函数的定义很重要,除了inline函数。如果没有这样的特殊规则,在多个翻译单元(或一个翻译单元不止一次包含)的头文件或源文件(通常是“头文件”)中使用初始化器(例如)const的变量的最简单声明,虽然很少)在程序中会违反 ODR,这使得使用const= xxxconst变量作为替换某些类似对象的宏是不可能的。

于 2016-09-06T14:26:01.007 回答
11

我认为C++ 中的内部和外部链接给出了清晰简洁的解释:

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

编译器默认符号链接如下:

非 const 全局变量默认有外部链接
const 全局变量默认有内部链接
函数默认有外部链接

于 2017-02-23T01:21:20.393 回答
8

基本上

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

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

  1. 默认情况下,全局变量是external linkage
  2. 但是,const全局变量是internal linkage
  3. 额外的,extern const全局变量是external linkage

关于 C++ 链接的一个很好的材料

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

于 2017-10-12T14:41:19.647 回答
7

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

  1. 内部链接:标识符只能在翻译单元内看到。
  2. 外部链接:标识符可以在其他翻译单元中看到(和引用)。
  3. 无链接:标识符只能在定义它们的范围内看到。链接不影响作用域

仅限 C++:您还可以在 C++ 和非 C++ 代码片段之间建立链接,这称为语言链接

来源:IBM 程序链接

于 2017-11-17T04:42:16.827 回答
2

在 C++ 中

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

全局变量和普通函数有外部联系。

文件范围内的静态对象或函数名称是翻译单元的本地名称。这就是所谓的 内部链接

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

于 2018-08-08T09:37:18.733 回答