参考1:C header files and compilation/linking
参考2:计算机系统基础(一)袁春风 (符号链接部分)
我们现在有一个简单的工程,有这么几个文件
1.t1.h
extern int x;void tt();
- t1.c
#include "t1.h"int x;void tt(){x = 100;
}
- main.c
#include <stdio.h>
#include "t1.h"int main(){tt();printf("x = %d\n",x);return 0;
}
现在,我们依次来看一下
- 头文件 和 C源文件 如何联系在一起
- 多文件如何变成1个可执行目标文件
预处理,组合头文件与包含它的C源文件
在32位Linux系统中。
我们执行gcc -E t1.c -o t1.i
,对源程序进行预处理,将头文件包含进来。
所谓预处理,就是将预编译命令处理掉,比如,把头文件的内容拷贝到C源文件中,因此,我们就能够理解.h和.c文件中全部变量的关系了,我们看一下生成的文件内容
# 1 "t1.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 31 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 32 "<command-line>" 2
# 1 "t1.c"
# 1 "t1.h" 1
extern int x;void tt();
# 2 "t1.c" 2int x;void tt(){x = 100;
}
可以看到,开始有一些记录的信息,看起来应该是注释,是一些说明性信息。
然后我们看到,之前头文件的内容在这个文件里面了。如果你把它近似地看为一个源文件,你就能大概理解全局变量声明和定义,以及不要重复定义等。
对于main.c文件的预处理,道理是一样的
然后,我们将t1.i
和main.i
分别生成其可重定位目标文件,最后链接起来,就生成了可执行目标文件。
gcc -c t1.i -o t1.o # 生成可重定位目标文件
gcc -c main.i -o main.o # 生成可重定位目标文件
gcc -o main main.o t1.o # 链接,生成可执行目标文件
./main # 运行可执行目标文件
最后,需要说明
对于函数的声明(头文件声明、外部声明、内部声明)与定义(内部定义、外部定义)
在c源文件中进行函数声明,然后使用它,在链接的时候,这个声明的函数(但未在该文件中定义)链接器会自动在其他的可重定位目标文件中寻找其定义,如果找到了就联系起来,否则就报错。这就意味着,所有的C源文件中的函数默认都是全局的,你可以在模块1声明函数a,然后调用它,在模块2中定义函数a,之后将两个模块链接起来生成可执行文件。
好吧,每次都声明很麻烦,所以,我们在模块2对应的头文件声明,然后模块1引入头文件,这样,我们就能够进行和之前一样的操作了,你知道的,头文件在预处理的时候会被包含进入源文件,这样,其实达到了和我们手动声明一样的效果。
如果你不想让函数是全局的,那就加上static
,这样,只有该源文件可以使用它了!
对于变量的定义与初始化
- 局部变量:只能在其
{ }
内使用 - static变量:只能在本模块内使用
- 全局变量:全部都可以用
- 本模块定义
- 外部定义
extern
对于本模块使用的,没得说,就是只有这个源文件能够使用这个变量!
只讨论全局变量。
- extern变量,不要初始化,只声明即可!
- 任何初始化的全局变量,全局范围内只能初始化1次,可以定义n次,但是最终内存空间中的,就是初始化的内个变量的位置,只有一个!
- 头文件一般包含函数声明,全局变量的定义似乎没必要,或者说,不要在头文件定义全局变量。
- 全局变量最好少出现,出现一次也就够了,在不同编译器下,要求不一样。少用。 比如在Linux的gcc下,不同C源文件,可以出现多个
int x
弱符号,但是Windows的VS下就不允许。
因此说,使用全局变量,最好
- 初始化全局变量
- 只定义一次
- 其他的模块如果要用,就声明
extern
表示引用外部定义,而不是再声明一个弱符号(不是不行,但是这样的话,gcc能用,VS就不能用) - 不要在头文件定义全局变量(头文件被多次包含的话…得定义多少次,恐怖)
注意
函数有
- 是否声明
- 是否定义
- 是否使用
对于任何模块,必须先声明,再使用,声明之后可以不定义,因为可以外部定义,但是被声明被使用的函数,必须有其定义。 要是声明之后没有使用也没有定义,其实也行,但是最好不要这样干,太奇怪了!
对于同一模块,先定义再使用也可以,但是不能先使用再定义,顺序很重要。
变量有
- 是否定义
- 是否初始化
- 是否使用
然后,还涉及到不同模块之间…