繁体   English   中英

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

[英]What is external linkage and internal linkage?

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

我也想知道什么意思

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

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

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

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

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

您可以使用externstatic关键字显式控制符号的链接。 如果未指定的联动是默认连接是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 (内部链接),不如使用匿名命名空间,您也可以将class es 放入其中。 尽管它们允许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
}
  • 默认情况下,全局变量具有外部链接 通过在另一个文件中给出匹配的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将其链接更改为 external 。 所以现在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是保持其在调用值函数的变量f() 与具有默认自动存储类的局部变量不同, nCall将仅在程序开始时初始化一次,而不是每次调用f()初始化一次。 存储类说明符static影响局部变量的生命周期,而不是其作用域。

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

希望有帮助!

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

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

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

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

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

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

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

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

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

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

请注意,对象是一个实体,但变量不是。 说到变量的链接,其实关心的是所指实体的名称(由特定的声明引入)。 名称的联动处于以下三种之一:无联动、内部联动或外部联动。

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

(糟糕......我发现我输入的内容只是在重复标准措辞......)

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

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

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

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

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

编译器默认符号的链接,使得:

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

基本上

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

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

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

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

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

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

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

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

来源: IBM 程序链接

在 C++ 中

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

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

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM