使用'extern'关键字

4

我对C语言中extern关键字的使用感到困惑。当它与变量一起使用时,它表示变量的声明。我在main()函数外部声明变量tmp,并在main()函数的一个独立块中定义它,但是当我在随后的块中打印该值时,我得到了一个"UNRESOLVED EXTERNAL LINK"的错误。请给我详细的解释。

#include <stdio.h>
extern int tmp ;
int main()
{
    {
        int tmp = 50;
    }
    {
        printf("%d",tmp);
    }
    return 0;
}


6
这应该会有所帮助:C语言中的 extern 变量是什么? - Gilles 'SO- stop being evil'
当我指出https://dev59.com/d3M_5IYBdhLWcg3wThR3#1433387时,我认为它是有用的背景阅读。我不认为它充分回答了这个具体问题,这就是为什么我不同意将早期的问题视为重复。 - Gilles 'SO- stop being evil'
5个回答

7
不; extern int tmp; 的意思是“在别处有一个变量tmp的定义”; 这是一个声明 —— 你可以引用tmp但它没有被定义。此外,当你在函数外写extern int tmp;时,意味着该变量将在函数外定义——它是一个全局变量,可能已在当前源文件或另一个源文件中定义。(在函数内部写extern int tmp;的规则比较复杂,我们现在不去讨论!)
函数中的局部变量int tmp = 50;与函数外声明的全局变量tmp没有关系。花括号内的局部变量将全局变量隐藏起来。(局部变量也未被使用。)虽然printf()语句引用了全局变量,但局部变量对于printf()而言不在作用域内。
因为你没有定义全局变量(例如,在文件底部添加int tmp = -2;),所以你的程序无法链接,并且除非你在此源文件中定义该变量或链接其他包含该变量定义的源文件,否则它将继续失败。

一个好的详细回答 :). 我稍微不同意,即用extern定义的全局变量不能在同一源文件中的其他位置进行定义。它将在同一翻译单元中,但不是同一源文件。如果您持不同意见,请告诉我。 - fkl
1
你的意思是说,你认为在函数作用域之外的源文件中,不能这样写:extern int i; int i = 97;?试一下——你可以……以任何顺序。一个是声明,另一个是定义;它们可以共存。你可以重复声明,但不能重复定义。 - Jonathan Leffler
嗯...这很有趣。我相当确定在我的职业生涯中至少曾经失败过一次。可能像你提到的那样,桌面操作系统的标准编译器(如gcc)允许它,而我的情况可能是嵌入式系统,例如arm、ppc或mips的gcc,因为我经常使用它们。但我会确保这是否被推荐为可移植的标准做法。感谢你指出这一点。 - fkl
请参考What are extern variables in C问题,获取详细解答。然而,良好的编程实践是在声明全局变量时定义一份头文件,并将其包含在定义全局变量的源文件中,以确保声明和定义的一致性。引用该全局变量的其他文件可以放心使用该声明。这种交叉检查非常重要,需要extern int global_var;int global_var = 12345;共存。 - Jonathan Leffler

3

这行:

 extern int tmp ;

说在其他地方寻找tmp变量的定义,这意味着在整个程序中查找变量定义的其他翻译单元

当你在main函数中定义int tmp时,它是局部的,即它没有任何外部链接

免责声明-关于这个问题,SO上有很多帖子,就像上面评论中提供的那个链接。无论我怎么添加,最终都会成为重复。然而,下面Jonathan leffler的回答非常好。


1
"elsewhere" 可以解释为文件作用域之外,甚至是不同的 "翻译单元"。 +1 虽然是第一个也是正确的答案。 - fkl
@fayyazkl,稍等一下,我添加一些细节!!谢谢!!顺便说一句 :) - 0decimal0

1

Extern是重新声明,因此它不会创建变量,而只是告诉编译器真正的声明在其他地方。您可以在一个源文件中使用它来引用另一个文件中的变量声明,或者在同一文件中使用它来表达您使用先前声明的全局变量。

因此,当您声明全局变量时

int a=5;

在同一源文件中使用函数,并且想要使用全局变量,但声明不在此处时,可以在函数体中添加“extern int a;”来明确告知使用了全局变量。
type func(arguments){
extern int a;
.
.
.

当 int a=5 在另一个源文件中时,您需要将其放置。

 extern int a; 

在源文件中,您实际上想要使用在前一个源文件中声明的全局变量a。

0
这是关于链接的内容。当您声明一个变量extern时,您给它外部链接,表示它在其他地方定义了全局链接。
在您的函数中,您正在定义一个名为tmp的变量,但它没有全局链接,它是一个局部变量。您必须在任何函数之外定义它以给它全局链接。
还有静态链接,这意味着变量是全局的,但仅限于当前编译单元(源文件)。

0
使用extern关键字,您只声明符号tmp。这意味着该符号在其他地方定义,并将在链接时解析。
因此,如果您没有提供定义符号的编译对象,则链接器会给出某种“未解决的符号”错误。
有关C中的声明或定义的更多详细信息,请参见以下问题。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接