我的问题是关于何时应该用extern
C中的关键字引用函数.
我没有看到何时应该在实践中使用它.在我编写程序时,我使用的所有函数都通过我包含的头文件提供.那么为什么extern
访问头文件中没有公开的东西会有用呢?
我可能会想到如何extern
正确地工作,如果是这样,请纠正我.
编辑:如果extern
是头文件中没有关键字的默认声明,你应该做些什么吗?
" extern
"改变了联系.使用关键字,假定函数/变量在其他位置可用,并且解析将延迟到链接器.
函数和变量的"extern"之间存在差异:在变量上它不会实例化变量本身,即不分配任何内存.这需要在其他地方完成.因此,如果您想从其他地方导入变量,这很重要.对于函数,这只告诉编译器链接是extern.由于这是默认值(您使用关键字"static"来表示函数未使用extern链接绑定),因此您无需显式使用它.
extern告诉编译器这个数据是在某处定义的,并且将与链接器连接.
在这里的回答的帮助下,在这里与几个朋友交谈是使用extern的实际例子.
示例1 -显示陷阱:
File stdio.h: int errno; /* other stuff...*/
myCFile1.c: #includeCode...
myCFile2.c: #includeCode...
如果链接了myCFile1.o和myCFile2.o,则每个c文件都有errno的单独副本.这是一个问题,因为所有链接文件中都应该提供相同的errno.
示例2 -修复.
File stdio.h: extern int errno; /* other stuff...*/
File stdio.c int errno;
myCFile1.c: #includeCode...
myCFile2.c: #includeCode...
现在,如果链接器链接了myCFile1.o和MyCFile2.o,它们都将指向相同的errno.因此,用extern解决实现.
已经声明extern
关键字对于函数来说是多余的.
对于在编译单元之间共享的变量,您应该在带有extern关键字的头文件中声明它们,然后在单个源文件中定义它们,而不使用extern关键字.单个源文件应该是共享头文件名称的文件,以获得最佳实践.
在C中,'extern'隐含在函数原型中,因为原型声明了一个在其他地方定义的函数.换句话说,函数原型默认具有外部链接; 使用'extern'很好,但是多余.
(如果需要静态链接,则必须在其原型和函数头中将该函数声明为"静态",并且这些函数通常都应位于相同的.c文件中).
许多年后,我发现了这个问题.在阅读了每个答案和评论后,我虽然可以澄清一些细节......这对于通过护目镜搜索来到这里的人来说非常有用.
问题是关于使用"extern"函数,所以我将忽略对全局变量使用"extern".
让我们定义3个函数原型
//-------------------------------------- //Filename: "my_project.H" extern int function_1(void); static int function_2(void); int function_3(void);
头文件可以由主源代码使用如下
//-------------------------------------- //Filename: "my_project.C" #include "my_project.H" void main(void){ int v1 = function_1(); int v2 = function_2(); int v3 = function_3(); } int function_2(void) return 1234;
为了编译和链接,我们必须在我们调用该函数的同一源代码文件中定义"function_2".另外两个函数可以在不同的源代码" .C"中定义,或者它们可以位于任何二进制文件( .OBJ,*.LIB,*.DLL)中,我们可能没有源代码.
让我们再次在不同的"*.C"文件中包含标题"my_project.H"以更好地理解差异.在同一个项目中,我们添加以下文件// --------------------------------------
//-------------------------------------- //Filename: "my_big_project_splitted.C" #include "my_project.H" void old_main_test(void){ int v1 = function_1(); int v2 = function_2(); int v3 = function_3(); } int function_2(void) return 5678; int function_1(void) return 12; int function_3(void) return 34;
需要注意的重要特性:当函数在头文件中定义为"静态"时,编译器/链接器必须在每个使用该包含文件的模块中找到具有该名称的函数的实例.
通过仅在该模块中使用"静态"重新定义原型,可以仅在一个模块中替换作为C库的一部分的功能.例如,替换对"malloc"和"free"的任何调用以添加内存泄漏检测功能.
函数并不真正需要说明符"extern".如果未找到"静态",则始终假定函数为"extern".
但是,"extern"不是变量的默认值.通常,任何定义要在多个模块中可见的变量的头文件都需要使用"extern".唯一的例外是如果保证头文件只包含在一个模块中.
然后,许多项目经理会要求将此变量放在模块的开头,而不是放在任何头文件中.一些大型项目,例如视频游戏模拟器"Mame"甚至要求这样的变量仅出现在使用它们的第一个函数之上.
关于extern
关键字的一篇非常好的文章以及示例:http://www.geeksforgeeks.org/understanding-extern-keyword-in-c/
虽然我不同意extern
在函数声明中使用是多余的.这应该是一个编译器设置.因此,我建议extern
在需要时使用函数声明.
如果程序中的每个文件首先编译为目标文件,则需要将目标文件链接在一起extern
.它告诉编译器"这个函数存在,但它的代码在别的地方.不要惊慌."