文章目录
1,小案例
一个单独的文件:add.c
int add(int a, int b) {
return a + b;
};
一个有main方法的文件:main.c
#include<stdio.h>
extern int add(int a, int b);
int main() {
printf("%d\n", add(1, 2));
return 0;
}
效果:
C语言的代码,想寻找一个东西,只需要extern声明一下即可。
不需要管文件名。
会生成两个obj文件,一个exe文件。
2,代码是如何运行的
翻译环境:变成exe的环境。
执行环境:运行exe的环境。
c:源代码,文本文件。
obj:目标文件,中间文件。
一个c文件产生一个obj文件,这个过程叫编译。
exe:二进制的指令。
由链接器处理所有obj文件,和标准库,得到一个exe,这个过程叫链接。
编译的过程还分三个:
- 预编译。
- 编译。
- 汇编。
3,用gcc处理案例
先编写两个c文件。
简写,运行
可以简写,直接生成app文件。
编译,链接,运行
用gcc -c xxx.c 的方式编译,得到对应的o文件。
再用gcc -o xxx a b c d 的方式进行链接。得到可执行文件。
最后,运行app。
预编译,编译,汇编,链接,运行
预编译:
编译:
汇编:
链接,运行:
4,图解
5,预编译过程
a)引入头文件
stdio.h变成了一堆函数。
b)删除注释
注释被去掉了。
c)定义符号被替换
#define的引用被替换成值。
(图中的代码不小心加了分号。。。)
6,编译过程
编译过程产生的是汇编语言代码。
参考《编译原理》。
看,天书!
7,汇编过程
汇编语言变成二进制的机器码。
一堆乱码。
其中会有一个东西叫符号表。
键是符号名,值是符号对应的地址。
8,链接过程
合并段表
将所有o文件有规则地合并在一起。
合并符号表,重定位符号表。
默认的符号表中,引用的一些符号的地址是没有意义的。
这个阶段,就是将正确的地址补充进去。
如果找不到符号,则会报错。
main能找到真正的add函数。