一. 概述
extern是在外部定义的全局变量,其作用域是从变量的定义处开始,到本程序文件的末尾。在此作用域内,全局变量可以为程序文件中的各个函数多引用。编译时,外部变量分配在静态存储区内。在extern声明外部变量的时候,类型名可以可不写, extern int A,B 等价于 extern A,B
二.利用extern在单个文件中扩展全局变量的作用域
如果外部(全局)变量不在文件的开头处定义,其有效作用范围只限于定义处到文件结束。那么如果我们想要在其定义处之前引用此变量,可以有两种方法。
1. 将此全局变量移至文件的开头处(所有要引用其的函数之前)。
2. 在其他函数调用其之前首先将其声明为extern变量,表明该变量是一个已知定义的外部变量,这样此变量的有效作用范围就可以从extern声明处开始到函数文件结束之后。
#include <iostream>
#include <stdio.h>
#include <vector>
using namespace std;
int max(int x, int y);
extern int A, B; //一旦加了extern,且后面已经有了定义也就意味着这里是声明了
//extern int A=13, B=5; //如果后面没有定义,这里就是连带定义和声明都做了,而且放在所有函数来使之前,其实和int A=13, B=5;的作用是一样的
int main()
{
//int max(int x, int y);
//extern int A, B; //在这里声明也是可以的
int res = max(A, B);
cout << res << endl;
}
int A = 13, B = 14;
int max(int x, int y)
{
int z = x > y ? x : y;
return z;
}
三.利用extern在多个文件中扩展全局变量的作用域
对于有多个源文件想要共享一个全局变量的值的时候怎么办呢?在一个源文件中定义的变量利用extern可以扩展这个变量的作用域从文件的开头一直到文件的结尾,那么如何将其作用域进一步扩展到其他文件呢?
首先,为了防止多次定义,全局变量的定义只能定义一次,我们可以选择在多个要使用这个变量的任一文件中定义这个变量(eg. int A),之后变量的声明可以声明多次,也就是我们在其他文件中的利用一句extern A,就可以让这个文件使用A这个变量。
四.extern关键字在实际编译链接中的行动
在编译时遇到extern,先会在本文件中找外部变量的定义,如果找到,那么本文件扩展作用域,如果找不到,就在链接是从其它文件中找外部变量的定义,如果找到,那么既然是一个已经在外边文件中定义过的变量,本文件不会再为其分配内存,将其作用域直接扩展到本文件,如果再找不到就按照出错处理。
五. 关于extern函数
以上我们都是介绍讲一个全局变量做extern,扩展其作用域,那么如果将extern加载函数的定义之前代表什么呢?
- 在定义函数的时候,日过在函数的定义的最左端添加关键字extern,则表示此函数是外部函数,可供其他函数使用,但是鉴于C语言规定,如果再定义函数的时候省略extern,则隐含为外部函数,因此我们一般定义的函数事实上默认加了extern的,也就是都可以有被其他文件中的函数调用的潜质。
- 如果外部文件想要使用此函数,需要首先利用extern对函数声明,表明该函数是在其他文件中定义的外部函数,或者利用extern声明也意味着扩展本文件中一些函数的作用范围到extern声明处。但是为了方便编程,C语言允许在声明函数的时候省写extern。
使用示例:
1.cpp中的内容
#include <iostream>
#include <stdio.h>
#include <vector>
using namespace std;
int max(int x, int y);
extern int A=13, B=5;
int show();
int main()
{
int res = max(A, B);
add();
cout << res << endl;
}
//int A = 13, B = 14;
int max(int x, int y)
{
int z = x > y ? x : y;
return z;
}
2.cpp中的内容
#include <iostream>
#include <stdio.h>
#include <vector>
using namespace std;
int show()
{
cout << "hello" << endl;
return 0;
}
直接编译这两个cpp是可以通过的。
六. 使用include命令与头文件
在工程中包含多个文件的时候,文件中互相联系通过两种方式连接:互相调用函数,互相使用共享的外部变量。这样就都是通过外部变量和外部函数来实现的,而调用的桥梁是通过外部变量和函数的声明。为了避免每次使用时写很多个声明,我们统一将一个源文件中的所有外部变量和函数都放在一个.h文件中(eg. test.h),这样在其他文件中,使用#include "test.h"
就相当于将test.h中所有的声明放在了其他文件的开始处。