嵌入式Linux下最为常用之C语言编译器GCC命令详解

GCC(GNU Compiler
Collection)是Linux下最为常用之C语言编译器,是GNU项目受到可ANSI
C标准的编译系统,能够编译用C、C++和Object
C等语言编写的次序。同时其可由此不同之前端模块来支撑各种语言,如Java、Fortran、Pascal、Modula-3和Ada等。

穿插一个玩笑: GNU意思是GNU’s not
Unix而不角马。然而GNU还是一个未拆分的连词,这实则是一个出自hacker的好玩:GNU是一个回文游戏,第一独字母G是凝聚的,你当然好于他举行ANU或者BNU。下面开始。

一.CC编译序过程分四独号

◆ 预处理(Pre-Processing)

◆ 编译(Compiling)

◆ 汇编(Assembling)

◆ 链接(Linking)

Linux程序员可以因自己的需要吃GCC在编译的别等级结束转去检查或用编译器在拖欠阶段的输出信息,或者对最后生成的二进制文件进行控制,以便通过入不同数量与档次之调剂代码来啊以后之调节做好准备。如同任何的编译器,GCC也供了灵活而强的代码优化功能,利用她好转变执行效率又强的代码。

GCC提供了30几近久警告信息及老三独警示级别,使用它们有助于增进程序的安居乐业以及可移植性。此外,GCC还针对性正规的C和C++语言进行了大气之扩展,提高程序的执行效率,有助于编译器进行代码优化,能够减轻编程的工作量。

二.简单编译命令

咱为Hello world程序来开我们的就学。代码如下:

/* hello.c */

#include 

int main(void)

{

printf (“Hello world!\n”);

return 0;

}

  1. 尽如下命令:$ gcc -o hello hello.c

运作而下 : $ ./hello

输出: Hello,world!

  1. 我们呢可以分步编译如下:

(1) $ gcc –E hello.c -o hello.i

//预处理了

//这早晚你看一下hello.i ,可以观看插进去了众物。

(2) $ gcc –S hello.i

//生成汇编代码后得了

(3) $ gcc –c hello.c

或者:

$ gcc -c hello.c –o hello.o

或者:

$ gcc -c hello.i -o hello.o

//编译结束

//生成 hello.o文件

(4) $ gcc hello.o –o hello.o

或者:

$ gcc –o hello hello.c

//链接了,生成可实施代码

  1. 俺们好管几乎独公文共编译生成同一个可执行文件。

比如:一个工程有main.c foo.c def.c生成foo的可执行文件。

编译命令如下:

$ gcc –c main.c foo.c def.c –o foo

或者:

$ gcc –o foo main.c foo.c def.c

三.库依赖

函数库是部分头文件(.h)和库房文件(.so或者.a)的聚集。Linux下之大多数函数都默认将头文件放到/usr/include/目录下,而仓库文件则坐/usr/lib/目录下,但毫无绝对如此。因此GCC设有补加头文件以及货栈文件之编译选项开关。

  1. 增补加头文件:-I

譬如在/home/work/include/目录下发生编译foo.c所需头文件def.h,为了给GCC能找到其,就需动用-I选项:

$ gcc foo.c -I /home/work/include/def.h -o foo

  1. 补偿加库文件:-L

比如说在/home/work/lib/目录下出链接所需库文件libdef.so,为了让GCC能找到她,就需要利用-L选项:

$ gcc foo.c –L /home/work/lib –ldef.a –o foo

征:-l选项指示GCC去连接库文件libdef.so。Linux下之库文件命名有一个约定,即库文件为lib三个假名开头,因为有的库文件都按照这约定,故在于是-l选项指定链接的库文件名时可以省去lib三独假名。

题外语:

Linux下之库文件分为动态链接库(.so文件)和静态链接库(.a文件)。GCC默看动态库优先,若想当动态库和静态库同时在的时链接静态库需要指明为-static选项。比如达例被假如还有一个libdef.a而而想链接libdef.a时候吩咐如下:

$ gcc foo.c –L /home/work/lib –static –ldef.a –o foo

四.代码优化

GCC提供不同水平的代码优化功能。开关选项是:-On,n取值为0暨3。默认为1。-O0表示不曾优化,而-O3凡是高优化。优化级别越强代码运行越快,但连无是富有代码都能加载最高优化,而应该看具体情况而一定。但一般都以-O2拣项,因为它在优化长度、编译时间及代码大小之间,取得了一个较漂亮之平衡点。

以下就段说的比较详细:

编译时采取选择-O可以告知GCC同时减多少代码的长度以及履行时间,其功效相当价于-O1。在当下无异级别上会进行的优化种虽然在目标电脑,但貌似还见面包括线程跳转(Thread
Jump)和延迟退栈(Deferred Stack
Pops)两栽优化。选项-O2报告GCC除了就有着-O1级别之优化之外,同时还要进行部分额外的调工作,如计算机指令调度等。选项-O3尽管除外完成具有-O2级别之优化之外,还连循环展开和任何一些以及计算机特性相关的优化办事。通常来说,数字越老优化的等越强,同时也尽管意味着程序的运转速度越来越快。

下面通过具体实例来感受一下GCC的代码优化功能,所用程序一旦清单3所出示。

/* optimize.c */

#include

int main(void)

{

double counter;

double result;

double temp;

for (counter = 0;

counter < 2000.0 * 2000.0 * 2000.0 / 20.0 + 2020;

counter += (5 – 1) / 4) {

temp = counter / 1979;

result = counter;

}

printf(“Result is %lf\n”, result);

return 0;

}

首先不加其余优化增选进行编译:

# gcc -Wall optimize.c -o optimize

借助Linux提供的time命令,可以约统计出该次在运作时所用之年月:

# time ./optimize

Result is 400002019.000000

real 0m14.942s

user 0m14.940s

sys 0m0.000s

联网下去使用优化增选来对代码进行优化处理:

# gcc -Wall -O optimize.c -o optimize

当同的法下又测试一下运作时刻:

# time ./optimize

Result is 400002019.000000

real 0m3.256s

user 0m3.240s

sys 0m0.000s

对照两不好实践的输出结果不难看出,程序的特性的确得到了好怪开间的改良,由原先的14秒缩短至了3秒。这个事例是专程针对GCC的优化职能而规划之,因此优化前后程序的实践进度发出了怪要命之改动。尽管GCC的代码优化功能十分强大,但当同样称佳绩之Linux程序员,首先还是如力求能手工编制出大质量之代码。如果编写的代码简短,并且逻辑性强,编译器就无见面开还多之干活,甚至从用不着优化。

优化虽然能为程序带来重新好的尽性,但以如下一些场合着应避免优化代码:


程序支付之早晚优化等越强,消耗在编译上的时空就是逾长,因此在付出的时太不用使用优化增选,只来到软件发行或支付了的下,才考虑对最终生成的代码进行优化。


资源受限的早晚有优化增选会增多而实行代码的体积,如果程序于运行时亦可申请到的内存资源异常紧张(如有实时嵌入式设备),那就绝不对代码进行优化,因为出于这带来的负面影响可能会见生非常严重的结果。


跟踪调试之早晚以对代码进行优化的当儿,某些代码可能会见于删除或改写,或者以赢得更出色的性质而展开重组,从而使跟踪及调节变得十分艰苦。