[英]What does “internal linkage” mean?
在标准中它说:
当名称具有内部链接时,其表示的实体可以通过同一翻译单元中其他范围的名称来引用。
和:
具有命名空间作用域(3.3.6)的名称具有内部链接(如果它是 - 一个显式声明为静态的变量,函数或函数模板的名称);
请考虑以下代码:
#include <stdio.h>
namespace A
{
/* a with internal linkage now.
Entity denoted by a will be referenced from another scope.
This will be main() function scope in my case
*/
static int a=5;
}
int main()
{
int a; //declaring a for unqualified name lookup rules
printf("%d\n",a);//-1216872448
}
我真的不明白标准中的定义。 这意味着什么:
它表示的实体可以通过同一翻译单元中其他范围的名称来引用。
翻译单元通常由单个源文件和所有#include
d文件组成,并生成一个目标文件 。
在命名空间范围的名称在默认情况下外部链接 ,这意味着你可以参考这个名字从其他翻译单元(带范围解析操作或使用指令)。 但是,如果使用static
限定名称,则链接将变为内部 ,并且名称不能在定义它的转换单元之外引用。
在您的例子,你可以访问a
如果命名空间A
,名字a
和main
方法是在同一个翻译单元。 但是,在main
,您声明另一个变量a
,隐藏a
命名空间A
。 和a
主没有初始化,所以当你打印,它实际上是从打印垃圾值a
中声明main
。 如果你想使用a
从A
在main
,请使用类似cout<<A::a
或使用using namespace A;
在包含main
的源文件中。
“翻译单元”是编译器一次处理的代码块的技术术语。 通常这是一个.cpp
源文件及其包含的所有头文件。
实际上,这通常意味着翻译单元被编译成目标文件。 该目标文件不是完整的程序; 它必须与其他目标文件“链接”才能生成最终程序。 “链接”过程简单地匹配在一个翻译单元中定义并在一个或多个其他翻译单元中使用的各种功能。
例如,您的翻译单元调用printf
,但对于定义(机器码) printf
其实是另一个翻译单元。 所以链接器必须知道1) printf
的实际定义在哪里,以及2)在你的代码中调用它的位置,因此它可以将1)的地址插入2)。
printf
是外部链接的一个例子; 它可以链接到翻译单元外部的东西。 另一方面,具有内部链接的东西只能在其翻译单元内链接。 因此,在您的示例中, main
可以访问A::a
,它在命名空间级别声明为static
,但在此转换单元之外定义的函数无法看到A::a
。 这是因为编译器省略了对象文件中链接表对A::a
的引用。
最后,你的例子中发生的事情是, main
看到的是它本身声明a
那个,它是未初始化的。 这就是它打印垃圾价值的原因。 如果您将main
更改为:
int main()
{
printf("%d\n", A::a);
}
它会打印5
。
它表示的实体可以通过同一翻译单元中其他范围的名称来引用。
为此,您必须了解实体和名称之间的区别。
在您的main函数中,您将创建一个新实体并为其命名a
。 该名称不是指名称空间A中名为a
的同一实体。它是一个不同的实体,不仅因为它具有不同的链接,还因为它位于不同的命名空间中。
默认情况下,局部变量没有链接,因此它们总是指定一个新实体。 例如
static int a = 5; // a new entity with name `a` that has internal linkage.
int main()
{
int a; // This is a new entity local to function main with no linkage.
// It isn't initialized, so you have undefined behavior if you try to
// access it.
}
在这种情况下,您有两个名为a
实体,但它们引用不同的实体,因为它们位于具有不同链接的不同范围内。
标准所指的情况是这样的:
static int a = 5; // A new entity with the name `a` that has internal linkage.
void f()
{
extern int a; // This is a new declaration for the same entity called `a` in
// the global scope.
}
现在您只有一个实体,但在两个不同的范围内仍有两个名称。 这两个名称指的是同一个实体。
这是一个非常棘手的问题。 因为里面的声明f()
有extern
,你说你要F公司a
指在别处定义的实体。 然而,由于已经有一份声明, a
在全球范围内被声明static
,它使a
有内在联系的,而不是外部链接。
请注意,对于具有内部链接的同一实体具有两个名称没有多大实际价值,因为您始终只需使用第一个名称。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.