extern的作用:抛开extern "c"这种特殊用法,它的作用简单来说就是改变了一个符号的作用域,这个符号可以是变量,可以是函数。一个全局变量原本他的作用域只在一个C文件内部,通过extern就可以让其扩大到整个工程。
一个实际的例子:
a_test.c
#include <stdio.h>
extern void fun();//引用外部函数
int a = 10;//定义一个全局变量
void main()
{
fun();
a ++;
fun();
return;
}
b_test.c
#include <stdio.h>
extern int a;
void fun()
{
int b = a;
printf("b: %d\n", b);
}
可以看到全局变量a和函数fun分别在b_test.o和a_test.o中是未定义符号,他们都来自外部,需要在连接的时候才会找到定义。
运行结果:
b: 10
b: 11
仔细分析这种写法,为了引用外部函数,无论从是代码的可读性,扩展性各种角度来看,显然使用更常见的头文件写法会更好,全局变量也是如此。所以改成下面这种写法。
b_test.c
#include <stdio.h>
#include "a.h"//将全局变量的extern封装到头文件中
void fun()
{
int b = a;
printf("b: %d\n", b);
}
a.h
extern int a;
上面这种写法在后续有其他.c需要使用这个全局变量的时候,都可以很方便的引用到,而不需要每个.c都extern。或者有新增的需要外部引用的全局变量,也只需要在头文件中不断新增即可。
另外还有一点,不要出现extern int a =3;这类的写法,如果带赋值的话,那就是定义而不是简单的声明了。可以看到用nm a对应的符号是D而不是U
这个时候再连接就会出现符号重定义了。就算这个写法用在原始定义上,这个例子中就是在a.c中写成extern int a = 10;其作用上也不会有任何差别。总而言之,extern 同时定义的写法毫无意义~~
最近公司发起排查,坚决除掉在.c中出现extern 外部符号的情况。这种问题的产生往往都是本领域要引用其他领域的全局变量,但是那个领域又没有提供相应的头文件,就会出现有人偷懒直接在.c中extern的情况。为了长远的发展角度,还是要勤快些呀。