当前位置:  开发笔记 > 编程语言 > 正文

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

如何解决《什么是外部联系和内部联系?》经验,为你挑选了8个好方法。

我想了解外部联系和内部联系及其区别.

我也想知道的意思

const默认情况下,变量内部链接,除非另有声明extern.

Motti.. 275

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

您可以使用externstatic关键字显式控制符号的链接.如果未指定链接,则默认链接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内部链接,最好使用匿名命名空间,也可以将classes 放入其中.匿名命名空间的链接在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在其中的所有标题.

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

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



1> Motti..:

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

您可以使用externstatic关键字显式控制符号的链接.如果未指定链接,则默认链接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内部链接,最好使用匿名命名空间,也可以将classes 放入其中.匿名命名空间的链接在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)
可能会大大增强这个答案的信息:1)在C++ 11中不再弃用静态.2)默认情况下,C++ 11中的匿名命名空间成员具有内部链接.请参见http://stackoverflow.com/questions/10832940/why-are-functions-objects-inside-anonymous-namespace-have-external-linkage
@Rajenda你会得到一个未解决的符号错误(抱歉九个月的延迟回答我错过了这个评论).
它是什么意思"外部链接但其他翻译单元无法访问"?它怎么可能无法到达但仍然是外部的?

2> 小智..:

当您编写实现文件(.cpp,.cxx等)时,编译器会生成一个转换单元.这是您的实现文件中的目标文件以及您#include在其中的所有标题.

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

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


除了一个小故障之外,我还要投票:翻译单元不是"某种程度上是目标文件",它是编译器_creates_目标文件的源代码.
@FrankHB,答案遗漏的"更重要的东西"是什么?

3> Rajendra Upp..:

默认情况下,全局变量具有外部链接.通过在另一个文件中提供匹配的extern声明,可以将其范围扩展到除包含它之外的文件.

通过在声明前加上关键字static,可以将全局变量的范围限制为包含其声明的文件.据说这些变量具有内部联系.

考虑以下示例:

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定义为整数变量.在函数体外定义的变量的默认链接是外部的.

2.cpp

#include 
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()时初始化一次.存储类说明符static会影响局部变量的生命周期,而不影响其范围.

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

希望有所帮助!



4> Libin Jose..:

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

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

范围:基本上我能看到多长时间和多远.

    局部变量:范围仅在函数内部.它驻留在RAM的STACK区域.这意味着每次调用一个函数时,所有作为该函数一部分的变量,包括函数参数都是新创建的,并且一旦控件退出函数就会被销毁.(因为每次函数返回时都会刷新堆栈)

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

    全局变量:这个范围适用于整个应用程序.它可以从应用程序的每个位置访问.全局变量也驻留在DATA段中,因为它可以在应用程序的每个位置访问,因此可以访问EXTERNAL Linkage

默认情况下,所有功能都是全局 如果您需要从外部隐藏文件中的某些函数,可以将static关键字作为前缀添加到函数中.:-)


@Libin:至于1)局部变量不必在堆栈上 - 它们通常在堆栈上但可以在寄存器中,在ARM环境中它们通常在寄存器中而不是在堆栈上(取决于某些因素 - 调用级别,数字)正式的args ..)
@Libin:至于1)如果你认为'flush'是覆盖 - 这是错误的.堆栈指针只是移动到不同的地方.没有"以前有效的本地变量"被"刷新"/清除等.您可以将变量范围与存储持续时间混合.范围告诉您可以访问var的位置.存储持续时间表示它存在多长时间.您可以使用静态存储持续时间的局部变量.这意味着它"永远"存在,但可以从声明的函数中访问.
请注意不准确的概念和明显的误解.严格地说,C中没有"全局"或"变量"(作为名词).你可能想要引用"文件范围对象"而不是"全局变量",而是谈论"范围"(在C中它是*标识符的属性*)是无稽之谈.(这两个术语在C++中的定义规范性地略有不同.)

5> FrankHB..:

在讨论这个问题之前,最好先了解术语翻译单元,程序和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变量替换某些类似对象的宏是不可能的.


这个答案听起来非常精通,可能非常准确(我无法判断),但很可能它不像许多人在这里查找这个问题所希望的那样容易理解,而不是直接阅读语言规范.至少对于我的需求,我会坚持使用已接受的答案,但仍然感谢您对语言规范的深入了解.

6> Nan Xiao..:

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

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

编译器默认符号链接,以便:

非const全局变量默认具有外部链接
Const 默认情况下,全局变量具有内部链接
函数默认情况下具有外部链接



7> arun pal..:

链接确定具有相同名称的标识符是否引用相同的对象,功能或其他实体,即使这些标识符出现在不同的翻译单元中也是如此。标识符的链接取决于如何声明。链接有三种类型:

    内部链接:标识符只能在翻译单元中看到。

    外部链接:标识符可以在其他翻译单元中看到(和引用)。

    没有链接:标识符只能在定义它们的范围内看到。链接不影响作用域

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

来源:IBM程序链接



8> Color..:

基本上

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++/

推荐阅读
周扒pi
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有