我想了解外部联系和内部联系以及它们的区别。
我也想知道是什么意思
const
默认情况下,变量在内部链接,除非另外声明为extern
.
当您编写实现文件(.cpp
,.cxx
等)时,您的编译器会生成一个翻译单元。这是您的实现中的源文件以及您#include
在其中的所有标头。
内部链接是指仅在翻译单元范围内的所有内容。
外部链接是指存在于特定翻译单元之外的事物。换句话说,可以通过整个程序访问,这是所有翻译单元(或目标文件)的组合。
正如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
(内部链接),不如使用匿名命名空间,您也可以将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
。据说这些变量具有内部联系。考虑以下示例:
void f(int i);
extern const int max = 10;
int n = 0;
int main()
{
int a;
//...
f(a);
//...
f(a);
//...
}
f
声明f
为具有外部链接的函数(默认)。它的定义必须稍后在此文件或其他翻译单元中提供(如下所示)。max
被定义为一个整数常量。常量的默认链接是internal。通过关键字将其链接更改为外部extern
。所以现在max
可以在其他文件中访问。n
被定义为一个整数变量。在函数体外部定义的变量的默认链接是external。#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;
}
max
被声明为具有外部链接。max
(带有外部链接)的匹配定义必须出现在某个文件中。(如 1.cpp 中)n
被声明为具有外部链接。z
被定义为具有内部链接的全局变量。nCall
指定nCall
为一个变量,该变量在对 function 的调用中保留其值f()
。与具有默认自动存储类的局部变量不同,nCall
它将仅在程序启动时初始化一次,而不是在每次调用f()
. 存储类说明符static
影响局部变量的生命周期,而不是其范围。注意:关键字static
起到双重作用。在全局变量的定义中使用时,它指定了内部链接。当用于局部变量的定义时,它指定变量的生命周期将是程序的持续时间,而不是函数的持续时间。
希望有帮助!
让我们谈谈'C'中的不同范围
范围:基本上是我能看到多长时间和多远。
局部变量:范围仅在函数内部。它位于 RAM 的堆栈区域。这意味着每次调用函数时,作为该函数一部分的所有变量,包括函数参数都是新创建的,并且一旦控制离开函数就会被销毁。(因为每次函数返回时都会刷新堆栈)
静态变量:这个范围是一个文件。它在声明它的文件
中的任何地方都可以访问。它位于 RAM 的 DATA 段中。因为这只能在文件内部访问,因此只能在内部链接中访问。任何
其他文件都看不到此变量。事实上 STATIC 关键字是我们可以引入某种级别的数据或
隐藏在“C”中的函数的唯一方法
全局变量:此范围适用于整个应用程序。它可以从应用程序的任何地方访问。全局变量也驻留在 DATA 段中,因为它可以在应用程序中的任何地方访问,因此可以访问外部链接
默认情况下,所有函数都是全局的。如果您需要从外部隐藏文件中的某些函数,您可以在函数前面加上 static 关键字。:-)
在说问题之前,最好准确地了解翻译单元、程序和C++的一些基本概念(实际上链接是其中之一)。您还必须知道什么是范围。
我将强调一些关键点,尤其是。以前的答案中缺少的那些。
链接是名称的属性,由声明引入。不同的名称可以表示相同的实体(通常是对象或函数)。因此,谈论实体的链接通常是无稽之谈,除非您确定实体只会由某些特定声明(通常是一个声明)中的唯一名称引用。
请注意,对象是实体,但变量不是。在谈论变量的链接时,实际上涉及到表示实体的名称(由特定声明引入)。名称的联动是三联之一:无联动、内联动或外联动。
不同的翻译单元可以通过头文件/源文件(是的,这是标准的措辞)包含共享相同的声明。因此,您可以在不同的翻译单元中引用相同的名称。如果声明的名称具有外部链接,则名称所指的实体的身份也是共享的。如果声明的名称具有内部链接,则不同翻译单元中的相同名称表示不同的实体,但您可以在同一翻译单元的不同范围内引用实体。如果名称没有链接,则您根本无法从其他范围引用实体。
(糟糕……我发现我输入的内容有点重复标准措辞……)
语言规范中还没有涵盖其他一些令人困惑的点。
__attribute__
或__declspec
) 或编译器选项,并且图像不是整个程序或从翻译单元翻译的目标文件,因此没有标准概念可以准确地描述它。由于符号不是 C++ 中的规范术语,它只是一个实现细节,尽管方言的相关扩展可能已被广泛采用。命名空间范围const
变量的链接规则有些特殊(特别不同于const
C语言文件范围内声明的对象,它也有标识符链接的概念)。由于ODR由 C++ 强制执行,因此在整个程序中保留不超过一个相同变量或函数的定义很重要,除了inline
函数。如果没有这样的特殊规则,在多个翻译单元(或一个翻译单元不止一次包含)的头文件或源文件(通常是“头文件”)中使用初始化器(例如)const
的变量的最简单声明,虽然很少)在程序中会违反 ODR,这使得使用const
= xxx
const
变量作为替换某些类似对象的宏是不可能的。
我认为C++ 中的内部和外部链接给出了清晰简洁的解释:
翻译单元是指实现 (.c/.cpp) 文件及其包含的所有头 (.h/.hpp) 文件。如果此类翻译单元内的对象或函数具有内部链接,则该特定符号仅对该翻译单元内的链接器可见。如果一个对象或函数具有外部链接,则链接器在处理其他翻译单元时也可以看到它。在全局命名空间中使用 static 关键字时,强制符号具有内部链接。extern 关键字导致符号具有外部链接。
编译器默认符号链接如下:
非 const 全局变量默认有外部链接
const 全局变量默认有内部链接
函数默认有外部链接
基本上
extern linkage
变量在所有文件中可见internal linkage
变量在单个文件中可见。说明: const 变量默认为内部链接,除非另有声明为 extern
external linkage
const
全局变量是internal linkage
extern const
全局变量是external linkage
关于 C++ 链接的一个很好的材料
http://www.goldsborough.me/c/c++/linker/2016/03/30/19-34-25-internal_and_external_linkage_in_c++/
链接确定具有相同名称的标识符是否引用相同的对象、函数或其他实体,即使这些标识符出现在不同的翻译单元中。标识符的链接取决于它的声明方式。有以下三种类型的链接:
仅限 C++:您还可以在 C++ 和非 C++ 代码片段之间建立链接,这称为语言链接。
来源:IBM 程序链接
在 C++ 中
文件范围内且未嵌套在类或函数中的任何变量在程序中的所有翻译单元中都是可见的。这称为外部链接,因为在链接时,链接器在该翻译单元外部的任何地方都可以看到该名称。
全局变量和普通函数有外部联系。
文件范围内的静态对象或函数名称是翻译单元的本地名称。这就是所谓的 内部链接
链接仅指在链接/加载时具有地址的元素;因此,类声明和局部变量没有链接。