//test.c
#include<stdio.h>
int main()
{
int x=,y=;
printf("x=%d y=%d\n",x,y);
return ;
}

1:预处理阶段,对包含的头文件(#include)和宏定义(#define,#ifdef等)进行处理。在上述的代码处理过程中,编译器将包含的头文件stdio.h编译进来,并且让用户使用选项”-E“
进行查看,该选项的作用是让gcc在预处理结束后停止编译过程。”.i“文件为已经过预处理的c程序。一下列出部分test.i文件的内容:
#  "test.c"
# "<built-in>"
# "<command-line>"
# "test.c"
# "/usr/include/stdio.h"
# "/usr/include/stdio.h"
# "/usr/include/features.h"
# "/usr/include/features.h"
# "/usr/include/sys/cdefs.h"
# "/usr/include/sys/cdefs.h"
# "/usr/include/bits/wordsize.h"
# "/usr/include/sys/cdefs.h"
# "/usr/include/features.h"
# "/usr/include/features.h"
# "/usr/include/gnu/stubs.h"
..................................................
extern int ftrylockfile (FILE *__stream) __attribute__ ((__nothrow__)) ; extern void funlockfile (FILE *__stream) __attribute__ ((__nothrow__));
# "/usr/include/stdio.h" # "test.c"
int main()
{
int x=,y=;
printf("x=%d y=%d\n",x,y);
return ;
}

2:编译阶段
接下来进行编译阶段,在这个阶段中,gcc首先要检查代码的规范性,是否有语法错误等,以确定代码实际要做的工作,在检查无误后,gcc把代码翻译成汇编语言。用户可以使用
“-S”选项来进行查看,该选项只进行编译而不进行汇编,结果生成汇编代码。
下面列出汇编代码test.s
    .file    "test.c"
.section .rodata
.LC0:
.string "x=%d y=%d\n"
.text
.globl main
.type main, @function
main:
pushl %ebp
movl %esp, %ebp
andl $-, %esp
subl $, %esp
movl $, (%esp)
movl $, (%esp)
movl $.LC0, %eax
movl (%esp), %edx
movl %edx, (%esp)
movl (%esp), %edx
movl %edx, (%esp)
movl %eax, (%esp)
call printf
movl $, %eax
leave
ret
.size main, .-main
.ident "GCC: (GNU) 4.4.6 20120305 (Red Hat 4.4.6-4)"
.section .note.GNU-stack,"",@progbits
3:汇编阶段
汇编阶段把编译生成的.s文件转换成目标文件,读者在此使用选项“-c"就可以看到汇编代码已经转换成”.o“的二进制目标代码了!

4:连接阶段
在成功编译后,之后进入连接阶段。这里涉及到一个重要的概念:函数库。
读者可以查看这个程序,在这个程序中并没有定义”printf"的函数实现,且在预编译中包含进来的“stdio"中也只有该函数的声明,而没有函数的实现,那么是在哪里实现了
“printf”函数呢?最后的答案是系统把这些函数的实现都放在名为lib.so.6的库文件中去了,在没有特别指定时,gcc会到系统默认的搜索路径”/usr/bin"下进行查找,也就是链接到libc.so.6函数库中去,这样就能调用函数“printf"了,而这正是动态链接的作用。
函数库有静态库和动态库两种。静态库是指编译链接时,将库文件的代码全部加入可执行文件中,因此生成的文件比较大,但在运行时也就不再需要库文件了。其后缀名通常为”.a“。动态库与之相反,在编译链接时并没有将库文件的代码加入到可执行文件中,而是在程序执行时加载库,这样可以节省系统的开销。一般动态库的后缀名为”.so“,如前面所述的lib.so.6就是动态库。gcc在编译时默认使用动态库。
完了链接之后,gcc 就可以生成可执行文件。

”-I dir"选项可以在头文件的搜索路径列表中添加dir目录。由于linux中头文件都默认放到了“usr/include/"目录下,因此,当用户希望添加放置在其他位置的头文件时,就可以通过”-I dir"选项来指定,这样,gcc就会到相应的位置查找对应的目录。
在include语句中,<>表示在标准路径中搜索头文件,“ ”表示在本目录中搜索。故在上例中,可把test.c中的#include<my.h>改为#include"my.h",就不需要加上“-I”选项了!!!!!!
下面链接的时候出现错误的!!!!

gcc 编译流程分析的更多相关文章

  1. GCC编译流程浅析

    GCC-GCC编译流程浅析 序言 对于大多数程序员而言,大家都知道gcc是什么,但是如果不接触到linux平台下的开发,鲜有人真正了解gcc的编译流程,因为windows+IDE的开发模式简直是一条龙 ...

  2. GCC 编译流程简介

    GCC-GCC编译流程 序言 对于大多数程序员而言,大家都知道gcc是什么,但是如果不接触到linux平台下的开发,鲜有人真正了解gcc的编译流程,因为windows+IDE的开发模式简直是一条龙全套 ...

  3. GCC编译流程及常用编辑命令

    GCC 编译器在编译一个C语言程序时需要经过以下 4 步: 将C语言源程序预处理,生成.i文件. 预处理后的.i文件编译成为汇编语言,生成.s文件. 将汇编语言文件经过汇编,生成目标文件.o文件. 将 ...

  4. 一次gcc编译失败分析

    1. 场景: ​ 在使用gcc编译时,编译器报错:xxx:'xxx'未定义的引用 2. 排查过程: 首先,我很自然的想到是不是自己使用了未定义的函数或者将函数名称写错了,在检查了一边过后,我发现自己使 ...

  5. gcc编译流程

    gcc的编译流程分为四个步骤,分别为: 预处理(Pre-Processing) 编译(Compiling) 汇编(Assembling) 链接(Linking) 以hello.c为例子,在这四个步骤中 ...

  6. 面试题----gcc的编译流程

    gcc编译流程 一.    编译与处理指令: gcc -E hello.c -o a.c 如果不使用-o指定输出的文件,会默认输出到终端.所以建议使用同时使用-o选项. 还要注意:编译时会保留#pra ...

  7. esp8266 SDK开发之编译流程

    最近刚完成自己8266的小项目,已经发布在github上,有兴趣的朋友可以看一下 github地址:esp-ujn 1. 通过MQTT协议与服务器交互 2. 内置HTTP服务器,支持通过浏览器进行参数 ...

  8. [uboot] (第四章)uboot流程——uboot编译流程

    http://blog.csdn.net/ooonebook/article/details/53000893 以下例子都以project X项目tiny210(s5pv210平台,armv7架构)为 ...

  9. [uboot] (第二章)uboot流程——uboot-spl编译流程

    http://blog.csdn.net/ooonebook/article/details/52949584 以下例子都以project X项目tiny210(s5pv210平台,armv7架构)为 ...

随机推荐

  1. OpenCV学习笔记(四十)——再谈OpenCV数据结构Mat详解

    原文:http://blog.csdn.net/yang_xian521/article/details/7107786 我记得开始接触OpenCV就是因为一个算法里面需要2维动态数组,那时候看cor ...

  2. discuz,ecshop的伪静态规则(apache+nginx)

    discuz(nginx): (备注:该规则也适用于二级目录) rewrite ^([^\.]*)/topic-(.+)\.html$ $/portal.php?mod=topic&topic ...

  3. C#应用视频教程1.3 Socket通信客户端完善

    我们先把前面的代码封装成一个完整的类,因为跟网络相关的方法并不一定是建立socket的服务器和客户端,所以还是应该把两个分开,比如获取本机IP,修改本机IP,PING远程主机这些事情应该放在一个单独的 ...

  4. JDK1.5 AtomicLong实例

    JDK1.5 AtomicLong实例 类 AtomicLong 可以用原子方式更新的 long 值.有关原子变量属性的描述,请参阅 java.util.concurrent.atomic 包规范.A ...

  5. Struts2之文件上传(单文件/多文件)

    <一>简述: Struts2的文件上传其实也是通过拦截器来实现的,只是该拦截器定义为默认拦截器了,所以不用自己去手工配置,<interceptor name="fileUp ...

  6. 完整的JavaScript版的信用卡校验代码

    function isValidCreditCard(type, ccnum) { if (type == "Visa") { // Visa: length 16, prefix ...

  7. 怎样线程安全地遍历List:Vector、CopyOnWriteArrayList

    遍历List的多种方式 在讲怎样线程安全地遍历List之前,先看看通常我们遍历一个List会採用哪些方式. 方式一: for(int i = 0; i < list.size(); i++) { ...

  8. CSDN日报20170401 ——《假设你还是“程序猿”,我劝你别创业!》

    [程序人生]假设你还是"程序猿".我劝你别创业! 作者:北漂周 在IT这一行做得久了,会接触到无数让人哭笑不得的外行话. 「我们就差一个写代码的了」是当中典型的一种,之所以黑它.不 ...

  9. 卡特兰数(Catalan数)

    首先奉上高中的排列组合公式,防止某些人忘记了 卡特兰数: 规定h(0)=1,而h(1)=1,h(2)=2,h(3)=5,h(4)=14,h(5)=42,h(6)=132,h(7)=C(14,7)-C( ...

  10. explain mysql性能优化

    1 使用explain语句去查看分析结果,如   explain select * from test1 where id=1; 会出现: id  selecttype  table  type po ...