为什么函数不需要extern,但变量需要呢?

3
抱歉,我的英文不太好。但我已经准备了一些示例,以便更清楚地表达我的问题。

a.cpp
#include <iostream>

using namespace std;

void funcfoo(){
    cout << "test only" << endl;
}

int varfoo = 10;



b.cpp

#include <iostream>

using namespace std;

extern void funcfoo();

extern int varfoo;

int main(){

    funcfoo();

    cout << varfoo;

    return 0;
}

然后我这样编译它:“cl b.cpp a.cpp”

我的问题是,为什么当我在void funcfoo()前面删除"extern"关键字时,它可以正常工作,但是当我在int var foo前面删除"extern"关键字时会出错?


2
函数默认具有外部链接性,关键字是多余的。请参见https://dev59.com/e3E85IYBdhLWcg3wzW3M。 - Wooble
4个回答

9
每行代码的含义是关键。 int varfoo 是一个变量的定义,而void funcfoo() 只是一个声明。您可以提供实体的多个声明,但只有一个定义。提供变量的声明且仅为声明的语法是通过添加extern关键字:extern int varfoo;是一个声明

3.1 [basic.def]/2 除非它声明一个未指定函数体(8.4)的函数,或包含 extern 指定符(7.1.1)或链接说明符25(7.5),并且没有初始化程序或函数体,否则声明就是定义。


void funcfoo(){ cout << "test only" << endl; } <--- 这是函数定义,对吗? - user1628256
@KarolyHorvath:我不确定。具有静态存储期的变量在进行任何其他初始化之前进行值初始化,但这并不意味着声明具有初始化程序(它没有)。 - David Rodríguez - dribeas
那么这里没有变量声明,只有一个函数? - user1628256
@KarolyHorvath:这个问题涉及到注释注意:在全局范围内,int varfoo;带有初始化。存在初始化程序和变量被初始化之间存在轻微差别。具有静态存储期的变量将进行值初始化,而不管是否存在初始化程序。在命名空间级别上声明int varfoo;即使保证初始化为0,也不包含初始化程序 - David Rodríguez - dribeas
@dribeas - David Rodríguez:额嗯呃呃呕吐.. 我觉得你的意思是一样的,只不过用了正确的术语。谢谢。 - Karoly Horvath
显示剩余25条评论

3
当你从 extern void funcfoo(); 中移除 extern 时,你正在前向声明它,这样下面的代码就会知道 funcfoo() 是什么。如果你对一个变量这样做,你实际上会实例化它,并与其他文件产生冲突。因此,extern 表示“它存在,请相信我 :)”,它会从其他文件中解析出来。

0

我知道可能有点晚了,但我希望这能在某种程度上有所帮助。请查看下面的链接,它会让你了解extern是什么以及它的工作原理。

http://www.geeksforgeeks.org/understanding-extern-keyword-in-c/

谢谢


0
另一种思考方式是,当您执行int varfoo时,会分配内存来保存变量,因此它既是定义又是声明;当您执行int foo()时,函数被声明但未定义,因此在某种程度上不会分配内存。对于函数,默认情况下链接是外部的,因此删除它并不重要,但对于变量,如果您说extern int varfoo,则编译器将不会为其分配内存--它将假定该变量在其他地方定义。

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