GCC编译流程浅析
GCC-GCC编译流程浅析
序言
对于大多数程序员而言,大家都知道gcc是什么,但是如果不接触到linux平台下的开发,鲜有人真正了解gcc的编译流程,因为windows+IDE的开发模式简直是一条龙全套服务,开发者只需要关系代码逻辑与功能实现即可,但是,在享受便利的同时,必然也牺牲了一些灵活性。
gcc是什么
国际惯例,先得介绍gcc是什么,gcc的原名为GNU C Compiler,专门针对C语言的编译器,而在后来计算机的发展中,GCC逐渐兼容了C++,java等语言,发展为扩展版的GCC,全称为 GNU compiler collection,事实上它是指一套编译器,而不再是单纯的C编译器,像g++,其实也是属于GCC工具中的一种。
gcc的基本使用
gcc的编译过程分多步完成,基本可分为4步:预编译,编译,汇编,链接,gcc的一般语法为
gcc [-option] <file> [-option] [-dst file]
举个例子,如果需要编译一个hello_world.c文件
gcc hello_world.c -o hello_world
在上述例子中,选择默认的编译选项,-o 为指定可执行文件的名称,上述生成hello_world可执行文件,如果不指定可执行文件名称,默认生成a.out可执行文件。
进入hello_world所在目录,即可使用./hello_world指令运行程序
常用gcc编译选项
-E
gcc的-E选项只对目标文件进行预编译处理
-S
gcc的-S选项只对目标文件进行预编译处理和编译处理,这里的编译处理仅仅是将预编译处理后的文件编译成汇编文件
-C
gcc的-C选项对目标文件进行预编译,编译,汇编处理,生成二进制目标文件
在默认情况下,gcc编译时执行预编译,编译,汇编和链接过程,直接生成可执行代码
-D
gcc的-D选项相当于在源文件中全局添加一个宏定义,一般在平台兼容或者程序模式切换中比较常见,例如:
#ifdef ARM
DO SOMETHING
#elif X86
DO SOMETHING
....
#endif
这时候在编译时或者在Makefile中加入 -DARM 或者 -DX86 来选择平台,而不用改源代码。
又或者,如果你在开发过程中,需要调试某些功能,经常会写一些调试代码,而有时候又想屏蔽部分调试代码,就可以这样实现:
#ifdef DEBUG_PART1
DO SOMETHING
#ifdef DEBUG_PART2
DO SOMETHING
...
#endif
-O(n)
gcc的-O选项规定了程序的优化等级,分为三个等级,分别是-O,-O2,-O3,所对应的优化等级依次增高.
gcc提供代码优化功能,可以基本做到同时优化程序空间和运行效率,但是并不是优化等级越高越好,因为优化等级越高就越可能出现一些潜在的风险,因为gcc的优化并不总是正确的,同时可能改变程序逻辑结构,加大调试难度,一个比较普遍的建议是在空间和效率可承受范围内选最低的优化等级。
-std=XXX
gcc的-std=XXX,这个XXX指定了gcc编译器的版本,如-std=c99或者-std=c++11,因为在默认编译条件下,可能不支持某些语言新版本的特性,当程序需要用到高版本语言特性时,则需要指定编译时对应的语言标准
gcc编译流程
预编译
预编译指将文件中包含的头文件展开,将所有的宏进行替换,同时将所有的条件编译解析出来添加到文件中。
所对应的编译指令为:
gcc -E file >> dst.i
需要注意的是,预编译并不生成相应的中间文件,直接输出到终端,因此需要将结果重定向到文件中以便查看。一个简单的hello_world.c文件经过预编译的过程将产生800多行的代码,我将在另一篇博客中详细讨论预编译中的宏、和条件编译。
编译
这个编译过程是我们通常讲的程序编译的一部分,是将经过预编译处理的代码编译成汇编代码。
所对应的编译指令为:
gcc -S file -o dst.s
汇编
汇编过程是将汇编语言的文件编译成目标文件,即二进制文件,我们通常所使用的静态库和动态库
编译指令为:
gcc -c file -o dst.o
链接
经过汇编生成的目标文件,如果是多个文件的编译,将会生成多个目标二进制文件,ld连接器将所有的二进制文件链接起来,根据平台的不同添加上不同的头部信息,分配内存空间,需要注意的是,在所有需要链接的目标文件中,有且仅有一个main()函数,main()函数作为程序入口函数只能有一个,否则会报错。
在链接过程中,还将涉及到链接静态库和动态库的问题。
很多朋友对库的概念应该不算陌生,经常会用到各种各样的库,但是仅仅停留在理解的层次而已,甚至都从来没有手动管理过库,其实可以说基本上每个程序员写的每个程序都要用到库函数,在C/C++语言中,最明显的例子就是包含头文件
#include <stdio.h>
其实,这个包含头文件的动作就是声明了glibc中的库函数,表明我的程序中需要调用到glibc中的库,而在程序进行链接的时候将会将glibc库链接进程序,但是这里有一个动态库和静态库的区分:
静态库:直接在链接阶段就将库文件链接到可执行文件中,最明显的缺点是可执行文件的尺寸变大。
动态库:在程序运行时才被载入,相对于静态库而言,就有几个明显的优点:
- 优化了静态库的浪费空间问题
- 由于只需要在内存中存在一个库文件,所有程序可以共享,所以在动态库后续的维护升级中,不必去一个个修改应用程序,而只需要修改库中的内容,降低耦合性。
gcc链接指令
-L 指定链接库的目录
-l 指定需要链接的库名称
接下来的博客会详细讲解静态库和动态库的生成以及使用。
好了,关于GCC编译流程的问题就到此为止了,如果朋友们对于这个有什么疑问或者发现有文章中有什么错误,欢迎留言
原创博客,转载请注明出处!
祝各位早日实现项目丛中过,bug不沾身.
(完)
GCC编译流程浅析的更多相关文章
- GCC 编译流程简介
GCC-GCC编译流程 序言 对于大多数程序员而言,大家都知道gcc是什么,但是如果不接触到linux平台下的开发,鲜有人真正了解gcc的编译流程,因为windows+IDE的开发模式简直是一条龙全套 ...
- GCC编译流程及常用编辑命令
GCC 编译器在编译一个C语言程序时需要经过以下 4 步: 将C语言源程序预处理,生成.i文件. 预处理后的.i文件编译成为汇编语言,生成.s文件. 将汇编语言文件经过汇编,生成目标文件.o文件. 将 ...
- gcc编译流程
gcc的编译流程分为四个步骤,分别为: 预处理(Pre-Processing) 编译(Compiling) 汇编(Assembling) 链接(Linking) 以hello.c为例子,在这四个步骤中 ...
- gcc 编译流程分析
//test.c #include<stdio.h> int main() { ,y=; printf("x=%d y=%d\n",x,y); ; } 1:预处理阶段, ...
- 面试题----gcc的编译流程
gcc编译流程 一. 编译与处理指令: gcc -E hello.c -o a.c 如果不使用-o指定输出的文件,会默认输出到终端.所以建议使用同时使用-o选项. 还要注意:编译时会保留#pra ...
- gcc编译工具生成动态库和静态库之一----介绍
1.库的分类 根据链接时期的不同,库又有静态库和动态库之分. 静态库是在链接阶段被链接的(好像是废话,但事实就是这样),所以生成的可执行文件就不受库的影响了,即使库被删除了,程序依然可以成功运行. ...
- gcc编译工具生成动态库和静态库
一. 库的分类 1.1. 静态库(.a) 1.1.1. 静态库的代码在编译过程中已经被载入可执行程序,因此体积比较大.所以生成的可执行文件就不受库的影响了,即使库被删除了,程序依然可以成功运行. 1. ...
- Gcc的编译流程分为了四个步骤:
http://blog.csdn.net/xiaohouye/article/details/52084770(转) Gcc的编译流程分为了四个步骤: 1.预处理,生成预编译文件(.文件): Gcc ...
- gcc 的编译流程 和gdb的调试方法
GCC的编译流程分为四个步骤: 预处理(Pre-Processing) 编译(Compiling) 汇编(Assembling) 链接(Linking) 可以看的出来文件大小 gdb 调试 gdb - ...
随机推荐
- ABAP基础篇2 数据类型
基本数据类型列表: 1.长度可变的内置类型(String.XString)1)string类型 在ABAP程序中,string类型是长度无限的字符型字段,可以和CHAR ,D,T ,I,N (F和P未 ...
- EasyDSS高性能RTMP、HLS(m3u8)、HTTP-FLV、RTSP流媒体服务器与EasyDSS流媒体解决方案的不同
背景分析 众所周知,立足于视频软件的开发,我们的产品很多.经常有客户问到我们产品的差别以及某个产品在某个系统架构中的具体定位,因此我想通过一系列的博客说明一下,不同产品之间的区别,以及在具体架构中自身 ...
- Python3 打包exe
cx_Freeze(不推荐) 以前只用 cx_Freeze 支持将 python3 打包成 exe ,示例如下: 在你要打包的 python 文件下新建这个 setup.py 文件: #!/usr/b ...
- .NET 文件上传和文件接收
有时候,我们需要在后台端发起向指定的“文件接收接口”的文件传输请求,可以采用HttpWebRequest方式实现文件传输请求. 1.HttpWebRequest文件传输请求的代码如下: 其中,url为 ...
- JS系列:数据类型详细讲解
ctrl+B加粗 ### 数据类型: - 1.number数字类型 NaN:not a number 不是一个数 ,但他是数字类型 isNaN:检测当前值是否不是有效数字,返回true代表不是有效数字 ...
- MySQL单机优化---分表、分区、分库
一.分表: 水平分表:根据条件把数据分为N个表(例如:商品表中有月份列,则可以按月份进行水平分表). 使用场景:一张表中数据太多,查询效率太慢. 当需要同时查询被水平分表的多张表时: 在两条SQL语句 ...
- python 之 面向对象 (异常处理)
7.15 异常处理 1.什么是异常 异常是错误发生的信号,程序一旦出错,如果程序中还没有相应的处理机制,那么该错误就会产生一个异常抛出来,程序的运行也随之终止 2.一个异常分为三部分: 异常的追踪信息 ...
- day04——列表、元组、range
day04 列表 列表--list 有序,可变,支持索引 列表:存储数据,支持的数据类型很多:字符串,数字,布尔值,列表,集合,元组,字典,用逗号分割的是一个元素 id() :获取对象的内存地址 ...
- 依赖注入 DI 控制反转 IOC 概念 案例 MD
Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ...
- HttpClient参观记:.net core 2.2 对HttpClient到底做了神马
.net core 于 10月17日发布了 ASP.NET Core 2.2.0 -preview3,在这个版本中,我看到了一个很让我惊喜的新特性:HTTP Client Performance Im ...