步骤
生成可以执行文件需要四个步骤:
预处理——编译——汇编——链接
在编译过程中,除非使用了-E、-S、-C选项(或者编译出错阻止了完整的编译过程)否则最后的步骤都是链接生成到最后的可执行文件。
比如:
gcc hello.c
他会输出一个默认的可执行程序 a.out,然后我们直接调用 ./a.out 来执行该应用程序。
下面我们逐步来看一下每一步都在做什么以及生成什么文件。
例子
我们用一个简单的例子来说明
#include<stdio.h>
#define MAX 20
#define MIN 10
int main()
{
printf("this is a compile sample\n");
printf("MAX = %d,MIN = %d,MAX + MIN = %d\n",MAX,MIN,MAX + MIN);
return 0;
}
这里我们可以一步生成可执行文件
gcc test.c
会生成默认可执行文件a.out
预处理 -E
作用:处理宏定义和include,去除注释,不会对语法进行检查,生成.i文件
命令:
gcc -E test.c -o test.i
我们预处理后生成test.i文件
我们打开test.i文件发现有很多东西,最下面出现的是
我们看到他将宏直接展开成数字,而宏定义已经没了。
编译 -S
作用:检查语法,生成汇编指令, .s文件。
命令:
gcc -s test.c -o test.s
可以看到生成的是汇编代码
汇编 -C
作用: 翻译成符合一定格式的机器代码, 生成.o文件。
命令
gcc -c test.c -o test.o
.o:object file(OBJ文件) 这里表现为二进制目标文件:
mac下生成的是mac目标文件
Linux下生成的是ELF目标文件
链接 -O
作用:链接就是将汇编生成的OBJ文件、系统库的OBJ文件、库文件链接起来,最终生成可以在特定平台运行的可执行程序。
gcc -o test test.c
这里我们生成的test就是一个可执行程序。-o是指定生成的可执行文件名称。他把前面几步都默认执行了。
在编译过程中,除非使用了-E、-S、-C选项(或者编译出错阻止了完整的编译过程)否则最后的步骤都是链接生成到最后的可执行文件。
所以一般我们都是直接执行-o选项生成可执行文件。
总结
一般我们其实不用关注前面三步,预处理——编译——汇编。因为这三步我们不需要去干预什么,都是机器自动检查错误或者生成一些东西。而最后一步链接的是链接一些库,这个就有我们可以操作的东西了,比如说我们指定一些可以连接的动态库,包括我们自己制作一些库放到给别人链接。这个我会在下一篇文章详细讲一下。