1、修饰变量的声明
举例来说,如果文件a.c需要引用b.c中变量int v,就可以在a.c中声明extern int v,然后就可以引用变量v。这里需要注意的是,被引用的变量v的链接属性必须是外链接(external)的,也就是说a.c要引用到v,不只是取决于在a.c中声明extern int v,还取决于变量v本身是能够被引用到的。这涉及c语言的另外一个话题——变量的作用域。能够被其他模块以extern修饰符引用到的变量通常是全部变量。还有很重要的一点是,extern int v可以放在a.c中的任何地方,比如你可以在a.c中的函数func定义的开头处声明extern int v,然后就可以引用到变量v了,只不过这样只能在函数func作用域中引用v罢了,这还是变量作用域的问题。对于这一点来说,很多人使用的时候都心存顾虑,好像extern声明只能用于文件作用域似的。在编译阶段,虽然a.c中找不到变量v的定义,但不会出错,因为extern修饰符告诉编译器该变量定义在了其他模块,它会在链接时在b.c模块中找到该变量。
2、修饰函数的声明
从本质上来说,变量和函数没有区别。函数名是指向函数二进制块开头处的指针。如果文件a.c需要引用b.c中的函数,比如在b.c中原型是int func(int mu),那么就可以在a.c中声明extern int func(int mu),然后就能使用func来做任何事情。就像变量的声明一样,extern int func(int mu)可以放在a.c中任何地方,而不定非要放在a.c的文件作用域的范围中。对其他模块中函数的引用,最常使用的方法是包含这些函数声明的头文件。使用extern和包含头文件来引用函数有什么区别呢?extern的引用方式是直接了当的,可以选择性的引用,这样做的一个明显的好处是,会加速程序的预处理过程,因为没有了#include的扩展时间。而包含头文件是比较简洁干净省事的做法,这样的好处是包含以后,头文件里所有的声明都可以使用了,不用一个一个使用extern来声明了,节省编码量。
有一点值得注意,全局变量的声明和定义,如果不加extern是无法区别的,比如int v,既是声明又是定义,默认值为0。所以如果只是声明,一定要用extern修饰,extern int v是声明,可以出现多次;int v是定义,只能出现一次。而函数的声明和定义是显而易见的,声明没有函数体,定义必须要有函数体,所以extern int func(int mu),和int func(int mu)是等价的,函数的声明有没有extern修饰都是可以的。
3、用于指示C或者C++函数的调用规范。比如在C++中调用c库函数,就需要在C++程序中用extern "c"声明要引用的函数。这是给链接器用的,告诉链接器在链接的时候用c函数规范来链接。主要原因是C++支持函数的重载,对于函数名的命名规则和C不一样。
原文地址:https://www.cnblogs.com/nchu-zf/p/10184351.html