先写一个程序:/*game.c*/ #include <stdio.h> #include <string.h> #include <stdlib.h> #define II 199 #define LL 2000 typedef struct { int a; float b; }double_data; int main() { printf("Hello world\n"); printf("II is %d,LL is %d\n",II,LL); double_data *p; p=malloc(sizeof(double_data)); }
首先,要经过编译,而编译即把.c文件转换为.s文件的汇编代码。而编译又可以分为两个步骤,1,编译预处理。把一些#include中的、define宏定义的全部用相应的代码和数字代替,这实际是增加了文件的大小的。<pre name="code" class="cpp">gcc -E -o game.i game.c
( 注意,-o 为生成文件(后面接要生成的文件名字),out 。。-E 即gcc 预编译的控制符号, 这样生成预处理文件game.i 可以查看到game.i 是很大的,因为它把#include 中的文件都加入进来了。2 ,编译过程,即生成汇编文件.s
gcc -S -o game.s game.c(or game.i)
3, 汇编过程,即生成目标文件(二进制的)
gcc -c -o game.o game.s(or game.i,game.c)
( 这里-c 为小写)4 ,最后,把目标文件和库文件(也是一种二进制文件)还有其他目标文件链接起来。。
gcc -o game game.o(or game.c game.i game.s)
链接没有任何的控制符,只需-o 即可。然后把需要链接的各个目标文件和库文件写在后面即可 总结一下:
-
预编译
将.c文件转化成.i文件
使用的gcc命令是:gcc–E
-
编译
将.c/.h文件转换成.s文件
使用的gcc命令是:gcc–S
-
汇编
将.s文件转化成.o文件
使用的gcc命令是:gcc–c
-
链接
将.o文件转化成可执行程序
使用的gcc命令是:gcc
另外:编译 只是把 c代码转为汇编代码,它的工作是检查词法和语法规则,所以,如果程序没有词法或则语法错误,那么不管逻辑是怎样错误的,都不会报错。
即起到的是翻译的作用,和程序的逻辑架构没有关系
汇编:即把汇编代码转为机器代码,这个也和编译的过程类似,也是一种翻译的过程,故一般和逻辑架构也无关。
但是,链接:把各种机器代码和库文件(也是机器代码的一种)按照规则合并成为一个可执行的文件,这个时候,就和逻辑架构有关了,比如目标代码间的函数调用,
比如库函数调用,比如全局或者局部变量的使用等等,故往往在链接的时候会出错。
总结起来编译过程就上面的四个过程:预编译处理(.c)-->编译、优化程序(.s、.asm)-->汇编程序(.obj、.o、.a、.ko)-->链接程序(.exe、.elf、.axf等)。
一般情况下,我们只需要知道分成编译和链接两个阶段,编译阶段将源程序(*.c)转换成为目标代码(一般是obj文件,至于具体过程就是上面说的那些阶段),链接阶段是把源程序转换成的目标代码(obj文件)与你程序里面调用的库函数对应的代码连接起来形成对应的可执行文件(exe文件)就可以了,其他的都需要在实践中多多体会才能有更深的理解。