我想了解外部联系和内部联系及其区别.
我也想知道的意思
const
默认情况下,变量内部链接,除非另有声明extern
.
Motti.. 275
正如dudewat所说, 外部链接意味着符号(函数或全局变量)可以在整个程序中访问,内部链接意味着它只能在一个翻译单元中访问.
您可以使用extern
和static
关键字显式控制符号的链接.如果未指定链接,则默认链接extern
用于非const
符号,而static
(内部)用于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
内部链接,最好使用匿名命名空间,也可以将class
es 放入其中.匿名命名空间的链接在C++ 98和C++ 11之间发生了变化,但主要的是它们无法从其他翻译单元访问.
namespace { int i; // external linkage but unreachable from other translation units. class invisible_to_others { }; }
"export"关键字的实现突出显示了声明为"static"的函数与未命名的命名空间中声明的函数之间的区别.为了尽可能地总结,在一个转换单元中使用export关键字声明的函数模板可以引用由于两阶段查找而在不同转换单元的未命名命名空间中定义的函数.(http://www.ddj.com/showArticle.jhtml?articleID=184401584) (11认同)
可能会大大增强这个答案的信息:1)在C++ 11中不再弃用静态.2)默认情况下,C++ 11中的匿名命名空间成员具有内部链接.请参见http://stackoverflow.com/questions/10832940/why-are-functions-objects-inside-anonymous-namespace-have-external-linkage (4认同)
@Rajenda你会得到一个未解决的符号错误(抱歉九个月的延迟回答我错过了这个评论). (2认同)
它是什么意思"外部链接但其他翻译单元无法访问"?它怎么可能无法到达但仍然是外部的? (2认同)
小智.. 257
当您编写实现文件(.cpp
,.cxx
等)时,编译器会生成一个转换单元.这是您的实现文件中的目标文件以及您#include
在其中的所有标题.
内部链接仅指翻译单元范围内的所有内容.
外部链接指的是存在于特定翻译单元之外的事物.换句话说,可以通过整个程序访问,这是所有翻译单元(或目标文件)的组合.
正如dudewat所说, 外部链接意味着符号(函数或全局变量)可以在整个程序中访问,内部链接意味着它只能在一个翻译单元中访问.
您可以使用extern
和static
关键字显式控制符号的链接.如果未指定链接,则默认链接extern
用于非const
符号,而static
(内部)用于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
内部链接,最好使用匿名命名空间,也可以将class
es 放入其中.匿名命名空间的链接在C++ 98和C++ 11之间发生了变化,但主要的是它们无法从其他翻译单元访问.
namespace { int i; // external linkage but unreachable from other translation units. class invisible_to_others { }; }
当您编写实现文件(.cpp
,.cxx
等)时,编译器会生成一个转换单元.这是您的实现文件中的目标文件以及您#include
在其中的所有标题.
内部链接仅指翻译单元范围内的所有内容.
外部链接指的是存在于特定翻译单元之外的事物.换句话说,可以通过整个程序访问,这是所有翻译单元(或目标文件)的组合.
默认情况下,全局变量具有外部链接.通过在另一个文件中提供匹配的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定义为整数常量.常量的默认链接是内部的.使用关键字extern将其链接更改为外部.所以现在可以在其他文件中访问max.
n定义为整数变量.在函数体外定义的变量的默认链接是外部的.
#includeusing 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是一个变量,它在函数f()的调用中保留其值.与具有默认自动存储类的局部变量不同,nCall仅在程序开始时初始化一次,而不是每次调用f()时初始化一次.存储类说明符static会影响局部变量的生命周期,而不影响其范围.
注意:关键字static扮演双重角色.在全局变量的定义中使用时,它指定内部链接.当在局部变量的定义中使用时,它指定变量的生命周期将是程序的持续时间而不是函数的持续时间.
希望有所帮助!
让我们谈谈'C'中的不同范围
范围:基本上我能看到多长时间和多远.
局部变量:范围仅在函数内部.它驻留在RAM的STACK区域.这意味着每次调用一个函数时,所有作为该函数一部分的变量,包括函数参数都是新创建的,并且一旦控件退出函数就会被销毁.(因为每次函数返回时都会刷新堆栈)
静态变量:这是针对文件的范围.它可以在
声明它的文件中的每个位置访问.它驻留在RAM的DATA段中.因为这只能在文件内访问,因此只能在INTERNAL链接中访问.任何
其他文件都看不到此变量.事实上,STATIC关键字是我们可以
在'C'中引入某种级别的数据或函数隐藏的唯一方法
全局变量:这个范围适用于整个应用程序.它可以从应用程序的每个位置访问.全局变量也驻留在DATA段中,因为它可以在应用程序的每个位置访问,因此可以访问EXTERNAL Linkage
默认情况下,所有功能都是全局 如果您需要从外部隐藏文件中的某些函数,可以将static关键字作为前缀添加到函数中.:-)
在讨论这个问题之前,最好先了解术语翻译单元,程序和C++的一些基本概念(实际上链接是一般的).您还必须知道什么是范围.
我会强调一些关键点,尤其是 以前的答案中缺少的那些.
Linkage是名称的属性,由声明引入.不同的名称可以表示相同的实体(通常是对象或函数).因此,谈论实体的链接通常是无稽之谈,除非您确定该实体仅由某些特定声明(通常是一个声明)中的唯一名称引用.
注意,对象是实体,但变量不是.在谈论变量的链接时,实际上是指定实体的名称(由特定声明引入).名称的链接是三者之一:没有联系,内部联系或外部联系.
不同的翻译单元可以通过标题/源文件(是的,它是标准的措辞)包含来共享相同的声明.因此,您可以在不同的翻译单元中引用相同的名称.如果声明的名称具有外部链接,则名称引用的实体的标识也是共享的.如果声明的名称具有内部链接,则不同翻译单元中的相同名称表示不同的实体,但您可以在同一翻译单元的不同范围内引用该实体.如果名称没有链接,则您根本无法从其他范围引用该实体.
(哎呀......我发现我输入的内容有点只是重复标准的措辞 ......)
还有一些其他混淆点,语言规范没有涉及.
可见性(名称).它也是声明名称的属性,但具有与链接不同的含义.
可见性(副作用).这与此主题无关.
可见性(符号).这个概念可以由实际实现使用.在这样的实现中,在对象(二进制)代码中具有特定可见性的符号通常是从实体定义映射的目标,该实体定义的名称在源(C++)代码中具有相同的特定链接.但是,通常不能保证一对一.例如,动态库映像中的符号只能在内部从源代码(通常包含某些扩展,__attribute__
或者__declspec
)或编译器选项的内部共享,并且映像不是整个程序或从中转换的目标文件.翻译单元,因此没有标准概念可以准确地描述它.由于符号在C++中不是一个规范术语,它只是一个实现细节,即使方言的相关扩展可能已被广泛采用.
可访问性.在C++中,这通常是关于类成员或基类的属性,这又是与主题无关的不同概念.
全球.在C++中,"global"指的是全局命名空间或全局命名空间范围.后者大致相当于C语言中的文件范围.在C和C++中,链接与范围无关,尽管范围(如链接)也与某些声明引入的标识符(在C中)或名称(在C++中)紧密相关.
命名空间范围const
变量的链接规则是特殊的(并且与const
在C语言中的文件范围中声明的对象特别不同,其也具有标识符链接的概念).由于ODR是由C++强制实施的,因此除了inline
函数之外,在整个程序中保持不超过一个相同变量或函数的定义是很重要的.如果没有这样的特殊规则const
,最简单的const
变量声明= xxx
包含多个翻译单元包含的标题或源文件(通常是"标题文件")中的初始值设定项(例如)(或者一个翻译单元不止一次包含,虽然很少)在程序中会违反ODR,这使得使用const
变量替换某些类似对象的宏是不可能的.
我认为C++中的内部和外部链接给出了一个清晰简洁的解释:
翻译单元是指实现(.c/.cpp)文件及其包含的所有标题(.h/.hpp)文件.如果此类翻译单元内的对象或函数具有内部链接,则该特定符号仅对该翻译单元内的链接器可见.如果对象或函数具有外部链接,则链接器在处理其他转换单元时也可以看到它.static关键字在全局命名空间中使用时,会强制符号具有内部链接.extern关键字导致符号具有外部链接.
编译器默认符号链接,以便:
非const全局变量默认具有外部链接
Const 默认情况下,全局变量具有内部链接
函数默认情况下具有外部链接
链接确定具有相同名称的标识符是否引用相同的对象,功能或其他实体,即使这些标识符出现在不同的翻译单元中也是如此。标识符的链接取决于如何声明。链接有三种类型:
内部链接:标识符只能在翻译单元中看到。
外部链接:标识符可以在其他翻译单元中看到(和引用)。
没有链接:标识符只能在定义它们的范围内看到。链接不影响作用域
仅C ++:您还可以在C ++和非C ++代码片段之间建立链接,这称为语言链接。
来源:IBM程序链接
基本上
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++/