C 语言中 extern 的用法

     在 C 语言中,修饰符 extern 用在变量或者函数的声明前,用来说明“此变量/函数是在
别处定义的,要在此处引用”。

1. extern 修饰变量的声明。
     举例来说,如果文件 a.c 需要引用 b.c 中变量 int v,就可以在 a.c 中声明 extern int v,
然后就可以引用变量 v。 能够被其他模块以 extern 修饰符引用到的变量通常是全局变量。 还
有很重要的一点是, extern int v 可以放在 a.c 中的任何地方,比如你可以在 a.c 中的函数 fun
定义的开头处声明 extern int v,然后就可以引用到变量 v 了,只不过这样只能在函数 fun 作
用域中引用 v 罢了,这还是变量作用域的问题。对于这一点来说,很多人使用的时候都心存
顾虑。好像 extern 声明只能用于文件作用域似的。

2. extern 修饰函数声明。
    从本质上来讲,变量和函数没有区别。函数名是指向函数二进
制块开头处的指针。如果文件 a.c需要引用 b.c中的函数,比如在 b.c中原型是 int fun(int mu),
那么就可以在 a.c 中声明 extern int fun( int mu),然后就能使用 fun 来做任何事情。就像变
量的声明一样, extern int fun( int mu)可以放在 a.c 中任何地方,而不一定非要放在 a.c 的
文件作用域的范围中。对其他模块中函数的引用,最常用的方法是包含这些函数声明的头文
件。
使用 extern 和包含头文件来引用函数有什么区别呢? extern 的引用方式比包含头文件
要简洁得多! extern 的使用方法是直接了当的,想引用哪个函数就用 extern 声明哪个函数。
这大概是 KISS 原则的一种体现吧!这样做的一个明显的好处是,会加速程序的编译(确切
的说是预处理)的过程,节省时间。在大型 C 程序编译过程中,这种差异是非常明显的。

3. 此外, extern 修饰符可用于指示 C 或者 C++函数的调用规范。
    比如在 C++中调用 C 库函数,就需要在 C++程序中用 extern “ C”声明要引用的函
数。这是给链接器用的,告诉链接器在链接的时候用 C 函数规范来链接。主要原因是 C++
和 C 程序编译完成后在目标代码中命名规则不同。

4. 举个简单的例子:
    用 C 语言编写程序的时候,我们经常会遇到这样一种情况:希望在头文件中定义一个全
局变量,然后包含到两个不同的 c 文件中,希望这个全局变量能在两个文件中共用。
举例说明:项目文件夹 project 下有 main.c、 common.c 和 common.h 三个文件,其中
common.h 文件分别#include 在 main.c 和 common.c 文件中。现在希望声明一个字符型变量
key,在 main.c 和 common.c 中公用。如下图所示:
有人想,既然是想两个文件都用,那就在 common.h 中声明一个 unsigned char key,然
后由于包含关系,在 main.c 和 common.c 中都是可见的,所以就能共用了。
这种想法其实是很多初学者都会想到的,想起来确实有道理,但是实际写出来,我们发
现编译的时候编译器提示出错,一般提示大概都类似于: Error: L6200E: Symbol key multiply
defined (by common.o and main.o). 也就是说编译器认为我们重复定义了 key 这个变量。这
是因为#include 命令就是原封不同的把头文件中的内容搬到#include 的位置,所以相当于
main.c 和 common.c 中都执行了一次 unsigned char key,而 C 语言中全局变量是项目内(或
者叫工程内)可见的,这样就造成了一个项目中两个变量 key,编译器就认为是重复定义。
正确的解决办法: 使用 extern 关键字来声明变量为外部变量。具体说就是在其中一个 c
文件中定义一个全局变量 key,然后在另一个要使用 key 这个变量的 c 文件中使用 extern 关
键字声明一次,说明这个变量为外部变量,是在其他的 c 文件中定义的全局变量。请注意我
这里的用词:定义和声明。例如在 main.c 文件中定义变量 key,在 common.c 文件中声明 key
变量为外部变量,这样这两个文件中就能共享这个变量 key 了,如下图所示。
代码如下(只写跟我们所说问题有关的部分):
( 1) main.c 文件
#include "common.h"
unsigned char key;
( 2) common.c 文件:
#include "common.h"
extern unsigned char key;

5. 实际运行的例子:
情景:在一个工程里面有两个文件 a.c and b.c,其中它们的内容如下:
a.c:
#include <stdio.h>
int i = 3;
int p(void)
{
printf("%d\n",i);
return 0;
}
b.c:
#include <stdlib.h>
extern int p(void);
extern int i;
int main()
{
p();
system("pause");
return 0;
} 在
b.c 里面调用 a.c 里面定义的变量和函数, 最后在 Dev c++里面运行, b.c 的输出结果
为: 3;

猜你喜欢

转载自blog.csdn.net/qq_29824717/article/details/81158100