来自https://www.quora.com/What-are-the-types-of-linkages-in-C-programming
外部链接,意味着可以在某处定义变量 在你正在处理的文件之外的其他地方,这意味着你可以定义 它在任何其他翻译单元内,而不是你当前的翻译单元(你 在另一个中定义关键字时,必须使用关键字extern 源代码)。
内部链接,意味着必须在您的中定义变量 翻译单位范围,这意味着它应该被定义为任何 包含的库,或在同一文件范围内。
无链接,指向默认函数和大括号范围等 作为在函数内定义一个自动变量,这将使 变量只能在该函数的范围内访问。
请注意:
默认情况下,任何全局对象都是外部链接,您可以使用关键字static来禁用它。
默认情况下,任何常量全局对象都在内部链接,您可以 使用关键字extern禁用它。
假设在file1中定义了一个全局变量,我想在file2中使用它。
在file1中,全局变量应使用关键字定义
extern
?
上面的引言似乎与自相矛盾:
"在其他源代码中定义关键字时,必须使用关键字extern"似乎应该说它应该。
"任何全局对象默认外部链接"似乎说它并不需要。
在file2中,我应该使用关键字extern
声明全局变量吗?
答案 0 :(得分:3)
tldr:您应该在头文件中声明带有extern
的变量,该文件包含在file1和file2中。然后,您应该仅在file1中定义变量。要定义变量,请将其声明为,而不是 extern
(并且没有static
)。
听起来你已经获得了extern
关键字和标准术语"外部链接"混淆了。
带有"外部链接的变量"可以从程序中的任何函数访问,只要该函数可以看到变量的声明。相比之下,一个带有内部联系的变量"最多可以从一个翻译单元访问#34; (单个源文件及其包含的所有文件),以及带有"无链接的变量"仅在单个函数中可见。 (我不记得在一个函数中声明的static
变量是否被认为具有内部链接或没有链接。)
应用于变量声明的extern
关键字具有两个效果。首先,它保证该变量将被赋予外部链接,即使声明在函数内部(不要这样做)。其次,更重要的是,它使声明不是一个定义。这意味着,如果你有这两个文件
/* file1.c */
extern int foo;
/* file2.c */
extern int foo;
int main(void) { return foo; }
他们的组合不是有效的计划。您将从链接器中收到错误,可能会读取类似"对foo
"的未定义引用。
要使其成为有效的程序,您必须从extern
的两个声明中的一个中删除foo
。然后该声明成为一个定义,程序将链接。 (此外,如果您希望在启动时它具有0以外的值,则可以为该声明提供初始化程序。)
如果您从extern
的定义的 中移除foo
,则结果为IIRC,已实现定义。一些C编译器将它们合并为一个全局变量,而其他C编译器将发出链接时错误。有时行为取决于变量是否具有初始值。
可以写
/* file1.c */
extern int foo;
/* file2.c */
extern int foo;
int foo;
这允许您将extern
声明放在两个.c
文件都包含的头文件中,这样可以降低声明出现不一致类型的风险(如果发生这种情况,程序将展示未定义的行为)。
答案 1 :(得分:1)
c11草案,6.2.2,第4节,陈述:
对于在其范围内使用存储类说明符extern声明的标识符 事先声明该标识符是可见的,31)如果先前声明指定内部或 外部链接,后面的声明中的标识符的链接是相同的 在先前声明中指定的联系。如果没有先前的声明可见,或者如果先前声明 声明指定没有链接,那么标识符有外部链接。
我不认为使用extern
关键字会有任何差异。一些实验也表明:
以下2编译:
extern int a;
extern int a;
int a = 20;
和
extern int a;
int a;
int a = 20;
但不是这一个:
extern int a;
int a = 10;
int a = 20;
然而,我有一些印象,一旦我读到动态链接涉及到Windows时的不同行为。我找不到它。如果有人能证实那就太好了。
答案 2 :(得分:1)
您引用的文字有很多错误。我建议不要依赖该网站的信息。
(在其他源代码中定义关键字时,您必须使用关键字
extern
。)
不正确,因为文件范围定义具有外部链接,除非使用static
关键字(或者没有使用说明符并且它们正在重新声明已使用static
关键字声明的内容)。 / p>
可以在定义中包含冗余extern
,但是也必须有一个初始化器(否则它将是声明而不是定义)。
内部链接意味着必须在翻译单元范围中定义变量,这意味着它应该在任何包含的库中定义,或者在同一文件范围中定义。
据推测,这意味着"包括标题",而不是"包含库"。
默认情况下,任何常量全局对象都在内部链接,您可以使用关键字extern禁用它。
这是错误的,"全球对象"除非用static
声明,否则有外部链接。作者可能将C与C ++混合在一起(在后者中,const
全局对象具有内部链接,除非另有说明)。
假设在file1中定义了一个全局变量,我想在file2中使用它。
// file1.h (or any other header)
extern object_t obj;
// file1.c
#include "file1.h"
object_t obj; // or: extern object_t obj = { 1, 2, 3 };
// file2.c
#include "file1.h"