我想了解外部连接和内部连接及其区别。 ios
我也想知道 c++
除非默认声明为
extern
,不然默认状况下const
变量内部连接。 函数
编写实现文件( .cpp
, .cxx
等)时,编译器会生成翻译单元 。 这是实现文件中的目标文件,以及#include
在其中的全部标头。 spa
内部连接仅指翻译单元范围内的全部内容。 翻译
外部连接是指存在于特定翻译单元以外的事物。 换句话说, 能够经过整个程序访问 ,这是全部翻译单元(或目标文件)的组合。 code
正如dudewat所说, 外部连接意味着在整个程序中均可以访问符号(函数或全局变量),而内部连接意味着只能在一个翻译单元中对其进行访问。 对象
您可使用extern
和static
关键字显式控制符号的连接。 若是未指定的联动是默认键是extern
用于非const
符号和static
(内部)为const
的符号。 ci
// 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 { }; }
extern
声明,能够将其范围扩展到除包含它以外的文件。 static
来将全局变量的范围限制为包含声明的文件。 听说这些变量具备内部联系 。 考虑如下示例: get
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
是保持其在调用值函数的变量f()
。 与具备默认自动存储类的局部变量不一样, nCall
在程序开始时仅初始化一次,而对于每次调用f()
nCall
不会初始化一次。 存储类说明符static
影响局部变量的生存期,而不影响其范围。 注意:关键字static
具备双重做用。 在全局变量的定义中使用时,它指定内部连接 。 当在局部变量的定义中使用时,它指定变量的生存期将是程序的持续时间,而不是函数的持续时间。
但愿有帮助!
让咱们来谈谈“ C”中的不一样范围
范围:基本上,我能够看到多长时间以及多远。
局部变量:做用域仅在函数内部。 它位于RAM的STACK区域中。 这意味着每次调用一个函数时,该函数的全部变量(包括函数参数)都会从新建立,并在控件退出该函数后销毁。 (由于每次函数返回时堆栈都会被刷新)
静态变量:此范围适用于文件。 它能够在文件中的任何位置访问
在其中声明。 它位于RAM的DATA段中。 因为只能在文件内部进行访问,所以只能进行内部连接。 任何
其余文件看不到该变量。 实际上,STATIC关键字是咱们能够引入某些级别的数据或功能的惟一方法
隐藏在“ C”中
全局变量:此范围适用于整个应用程序。 它能够从应用程序的任何位置访问。 全局变量也驻留在DATA段中,由于能够在应用程序中的每一个位置访问它,所以能够进行EXTERNAL连接
默认状况下,全部功能都是全局的。 若是须要从外部隐藏文件中的某些功能,则能够在该功能的前面加上static关键字。 :-)
在谈论这个问题以前,最好准确地了解术语翻译单元 , 程序和C ++的一些基本概念 (实际上,连接一般是其中之一)。 您还必须知道什么是范围 。
我会强调一些要点,特别是。 先前答案中缺乏的那些。
连接是名称的属性,由声明引入。 不一样的名称能够表示相同的实体 (一般是对象或函数)。 所以,谈论实体的连接一般是胡说八道,除非您肯定该实体将仅由某些特定声明(不过一般是一个声明)中的惟一名称引用。
请注意, 对象是实体,但变量不是。 在讨论变量的连接时,实际上要关注所表示实体的名称(由特定声明引入)。 名称的连接是如下三种之一:无连接,内部连接或外部连接。
不一样的翻译单元能够经过头文件/源文件共享相同的声明(是的,这是标准的措词)。 所以,您能够在不一样的翻译单位中使用相同的名称。 若是声明的名称具备外部连接,则该名称引用的实体的身份也将共享。 若是声明的名称具备内部连接,则不一样翻译单位中的相同名称表示不一样的实体,可是您能够在同一翻译单位的不一样范围内引用该实体。 若是名称没有连接,则根本没法从其余范围引用该实体。
(糟糕...我发现我键入的内容只是在重复标准措辞 ...)
语言规范中尚未涵盖其余一些使人困惑的地方。
__attribute__
或__declspec
)或编译器选项在内部在该映像中指定,而且该映像不是整个程序或目标文件从翻译单元翻译过来的,所以没有标准的概念能够准确地描述它。 由于符号不是C ++中的规范术语,因此它仅是实现细节,即便方言的相关扩展可能已被普遍采用。 名称空间范围const
变量的连接规则是特殊的(特别不一样于C语言中在文件范围中声明的const
对象,该对象也具备标识符连接的概念)。 因为ODR是由C ++强制执行的, 所以对于整个程序中发生的同一变量或函数,除了inline
函数外,不要超过一个定义 , 这一点很重要 。 若是没有这样特殊的const
规则,则最简单的const
变量声明在多个翻译单元(或一个翻译单元包含)的头文件或源文件(一般是“头文件”)中带有初始化程序(例如= xxx
)程序中会屡次(尽管不多)违反ODR,这使得没法使用const
变量替换某些相似于对象的宏。