什么是外部联系和内部联系?
我想了解外部联系和内部联系及其差异。
我也想知道的意思
const
variables默认内部链接,除非另外声明为extern
。
当您编写实现文件( .cpp
, .cxx
等)时,编译器会生成一个翻译单元 。 这是你的实现文件中的目标文件加上#include
d中的所有头文件。
内部联系是指在翻译单位范围内的一切。
外部联系是指超出特定翻译单位的东西。 换句话说, 可以通过整个程序来访问 ,这是所有翻译单元(或对象文件)的组合。
正如dudewat所说, 外部链接意味着符号(函数或全局variables)在整个程序中都是可访问的,而内部链接意味着它只能在一个翻译单元中访问。
您可以使用extern
和static
关键字显式控制符号的链接。 如果未指定链接,则对于非常量符号,默认链接是extern
对于const
符号,默认链接是static
(内部)。
// 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
内部链接,最好使用匿名命名空间 ,也可以将class
放入其中。 匿名命名空间的链接已经在C ++ 98和C ++ 11之间改变了,但最主要的是它们不能从其他的翻译单元访问。
namespace { int i; // external linkage but unreachable from other translation units. class invisible_to_others { }; }
- 全局variables默认具有外部链接 。 通过在另一个文件中给出一个匹配的extern声明,它的范围可以扩展到除包含它之外的文件。
- 全局variables的范围可以通过在声明前添加关键字static来限制为包含声明的文件。 据说这些variables具有内部联系 。
考虑下面的例子:
1.cpp
void f(int i); extern const int max = 10; int n = 0; int main() { int a; //... f(a); //... f(a); //... }
- 函数f的签名将f声明为具有外部链接的函数(默认)。 其定义必须在本文档或其他翻译单元(稍后给出)中提供。
- max被定义为一个整数常量。 常量的默认链接是内部的 。 它的连接被更改为外部关键字extern 。 所以现在max可以在其他文件中访问。
- n被定义为一个整数variables。 在函数体外定义的variables的默认链接是外部的 。
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; }
- 最大声明是有外部链接 。 max(与外部链接)的匹配定义必须出现在某个文件中。 (如1.cpp)
- n被宣布具有外部联系 。
- z被定义为具有内部连接的全局variables。
- nCall的定义指定nCall是一个在函数f()的调用中保留其值的variables。 与具有默认自动存储类的局部variables不同,nCall在程序开始时只会初始化一次,而不会在每次调用f()时被初始化一次。 存储类说明符静态影响局部variables的生存期而不影响其范围。
注意: 静态关键字起着双重作用。 当用于全局variables的定义时,它指定了内部连接 。 当在局部variables的定义中使用时,它指定variables的生命周期将是程序的持续时间,而不是函数的持续时间。
希望有所帮助!
在'C'方面(因为static关键字在'C'和'C ++'之间有不同的含义)
让我们谈谈“C”中的不同范围
范围:基本上我能看到多久,有多远。
-
局部variables:范围只在一个函数内。 它驻留在RAM的STACK区域。 这意味着每次调用某个函数时,包含函数参数在内的所有variables都是新创build的,并且一旦控件离开函数就会被销毁。 (因为每次函数返回都会刷新堆栈)
-
静态variables:这是一个文件的范围。 它可以在文件的每个地方访问
在哪里宣布。 它驻留在RAM的DATA段中。 因为这只能在文件内部进行访问,因此只能在INTERNAL内部进行访问。 任何
其他文件不能看到这个variables。 实际上,STATIC关键字是我们能够引入某种级别的数据或function的唯一方式
藏在'C' -
全局variables:这个范围适用于整个应用程序。 它可以在应用程序的每个地方访问。 全局variables也驻留在数据段中因为它可以在应用程序的每一个地方访问,因此可以访问外部链接
默认情况下所有function都是全局的 如果您需要从外部隐藏文件中的某些function,则可以将静态关键字添加到该函数的前缀。 🙂
在谈论这个问题之前,最好是准确地知道术语翻译单元 , 程序和C ++的一些基本概念 (实际上是一般的连接)。 你也必须知道什么是范围 。
我会强调一些重点,尤其是 那些在以前的答案失踪。
联系是一个名称的属性,由声明引入。 不同的名称可以表示同一个实体 (通常是对象或函数)。 所以谈论一个实体的链接通常是无稽之谈,除非你确定该实体只能通过某些特定声明(通常是一个声明)的唯一名称来引用。
注意一个对象是一个实体,但一个variables不是。 在谈到一个variables的连接时,实际上所指示的实体的名称(由特定的声明引入)是关心的。 这个名字的联系是三个之一:没有联系,内部联系或者外部联系。
不同的翻译单元可以通过标题/源文件(是的,这是标准的措词)包含共享相同的声明。 所以你可以用不同的翻译单位来表示同一个名字。 如果声明的名称具有外部链接,则由名称引用的实体的身份也是共享的。 如果声明的名称具有内部链接,则不同翻译单元中的同名表示不同的实体,但可以将该实体引用到同一翻译单元的不同范围内。 如果这个名字没有链接,那么你根本就不能把这个实体从其他作用域引用。
(糟糕…我发现我input的内容有些只是重复了标准的措词 …)
还有一些其他令人困惑的地方,不在语言规范的范围之内。
- 可视性(名称)。 它也是一个声明名称的属性,但是具有不同于链接的含义 。
- 可见性(副作用) 。 这与这个话题无关。
- 可见性(符号的)。 这个概念可以被实际的实现使用 。 在这种实现中,对象(二进制)代码中具有特定可见性的符号通常是从源(C ++)代码中名称具有相同特定链接的实体定义映射的目标。 但是,通常不能保证一对一。 例如,dynamic库图像中的符号只能在源代码内部(通常涉及
__attribute__
或__declspec
)或编译器选项在内部指定,图像不是整个程序或目标文件由翻译单位翻译,因此没有一个标准的概念可以准确地描述它。 由于符号在C ++中不是一个规范术语,它只是一个实现细节,尽pipe方言的相关扩展可能被广泛采用。 - 可访问性。 在C ++中,这通常是关于类成员或基类的属性 ,这又是一个与主题无关的不同概念。
- 全球。 在C ++中,“全局”是指全局名称空间或全局名称空间作用域。 后者大致相当于C语言中的文件范围 。 在C和C ++中,链接与范围无关,尽pipe范围(如链接)也与一些声明引入的标识符(C)或名称(C ++)密切相关。
命名空间范围const
variables的链接规则是一些特殊的东西(特别是与C语言中的文件范围中声明的const
对象不同,它也具有标识符链接的概念)。 由于ODR是由C ++强制执行的, 因此除了inline
函数以外,在整个程序中保持不超过一个相同variables或函数的定义是很重要的 。 如果不存在const
这种特殊规则,那么在多个翻译单元所包括的头文件或源文件(通常是“头文件”)中(或者由一个翻译单元所包括的),具有初始化符(例如= xxx
)的const
variables的最简单的声明不止一次,尽pipe很less)在一个程序中会违反ODR,这使得使用const
variables来替代一些对象类的macros是不可能的。
我认为C ++中的内部和外部链接给出了一个清晰而简洁的解释:
翻译单元指的是一个实现(.c / .cpp)文件和它包含的所有头文件(.h / .hpp)。 如果这样的翻译单元内的对象或function具有内部链接,那么该特定的符号仅对该翻译单元内的链接器可见。 如果对象或函数具有外部链接,则链接器在处理其他翻译单元时也可以看到它。 static关键字在全局名称空间中使用时会强制符号具有内部链接。 extern关键字导致符号具有外部链接。
编译器默认符号链接,以便:
非常量全局variables默认具有外部链接
Const全局variables默认具有内部链接
函数默认具有外部链接
基本上
- 所有文件中都可以看到
extern linkage
variables -
internal linkage
variables在单个文件中是可见的。
说明:默认情况下,constvariables内部链接,除非另外声明为extern
- 全局variables默认为
external linkage
- 但是,
const
全局variables是internal linkage
- 额外的,
extern const
全局variables是external linkage
关于C ++连接的一个很好的材料
http://www.goldsborough.me/c/c++/linker/2016/03/30/19-34-25-internal_and_external_linkage_in_c++/