GCC编译器(GNU C Compiler)是GNU组织的一款开源 编译器,它是Linux环境下的默认C语言编译器。它处理能够高效的编译C语言以外,还可以编译其他语言。并且,现在的GCC已经不光包括编译器本身,还包含了编译过程中的工具链。

1 GCC编译流程

在学习使用GCC编译程序之前,首先要知道编译C程序的基本流程,一般情况下分为下面四步:

(1) 对C语言进行预处理,生成*.i文件。

(2) 将上一步生成的*.i文件编译生成汇编语言文件,后缀名为*.s

(3) 将汇编语言文件*.s经过汇编,生成目标文件,后缀名为*.o

(4) 将各个模块的*.o文件链接起来,生成最终的可执行文件

2 GCC常用选项

GCC的编译选项非常多,现在有上千个,但是我们常用的并不多,下面我们只介绍其中非常实用的几个。

在这之前,我们先编写下面的几个源文件,以备测试只用。

 1 //main.c
2 #include <stdio.h>
3
4 extern int add(int a, int b);
5 extern int mul(int a, int b);
6
7 int main(void)
8 {
9 int a = 10, b = 5;
10 int result;
11
12 result = add(a, mul(a, b));
13 printf("result = %d\n", result);
14 return 0;
15 }
1 //test1.c
2 int add(int a, int b)
3 {
4 return a+b;
5 }
1 //test2.c
2 int mul(int a, int b)
3 {
4 return a*b;
5 }

2.1 -E选项

  该选项对C语言源文件进行预处理,但是并不编译该程序。对于一般的预处理问题(比如,宏的展开问题、文件的包含问题等),可以使用这个选项进行查看。另外,如果直接使用此选项,程序会将预处理结果直接输出到终端,不便于查看,因此,一般可以使用重定向将程序输出结果保存到一个文本文件中,格式如下:

gcc -E source.c > output

如果我们对main.c执行预编译,得到的output文件内容如下:

  1 # 1 "main.c"
2 # 1 "<command-line>"
3 # 1 "/usr/include/stdc-predef.h" 1 3 4
4 # 1 "<command-line>" 2
5 # 1 "main.c"
6
7 # 1 "/usr/include/stdio.h" 1 3 4
8 # 27 "/usr/include/stdio.h" 3 4
9 # 1 "/usr/include/features.h" 1 3 4
10 # 374 "/usr/include/features.h" 3 4
11 # 1 "/usr/include/i386-linux-gnu/sys/cdefs.h" 1 3 4
12 # 385 "/usr/include/i386-linux-gnu/sys/cdefs.h" 3 4
13 # 1 "/usr/include/i386-linux-gnu/bits/wordsize.h" 1 3 4
14 # 386 "/usr/include/i386-linux-gnu/sys/cdefs.h" 2 3 4
15 # 375 "/usr/include/features.h" 2 3 4
16 # 398 "/usr/include/features.h" 3 4
17 # 1 "/usr/include/i386-linux-gnu/gnu/stubs.h" 1 3 4
18
19
20
21
22
23
...............................
826
827 extern int pclose (FILE *__stream);
828
829
830
831
832
833 extern char *ctermid (char *__s) __attribute__ ((__nothrow__ , __leaf__));
834 # 913 "/usr/include/stdio.h" 3 4
835 extern void flockfile (FILE *__stream) __attribute__ ((__nothrow__ , __leaf__));
836
837
838
839 extern int ftrylockfile (FILE *__stream) __attribute__ ((__nothrow__ , __leaf__)) ;
840
841
842 extern void funlockfile (FILE *__stream) __attribute__ ((__nothrow__ , __leaf__));
843 # 943 "/usr/include/stdio.h" 3 4
844
845 # 3 "main.c" 2
846
847 extern int add(int a, int b);
848 extern int mul(int a, int b);
849
850 int main(void)
851 {
852 int a = 10, b = 5;
853 int result;
854
855 result = add(a, mul(a, b));
856 printf("result = %d\n", result);
857 return 0;
858 }

当然,我们也可以使用接下来要介绍的-o命令来指定输出文件名称,格式如下:

gcc -E source.c -o source.i

使用该命令对main.c进行预处理,得到的main.i文件内容与之前重定向输出得到的output文件的内容完全相同。

2.2 -S选项

  该选项(大写S)将C语言源文件编译生成汇编语言文件,但是并不汇编该程序。注意:汇编过程的作用是将汇编语言文件编译成目标文件*.o,而-S选项的作用是得到汇编语言文件*.s。该选项的使用方法为:

gcc -S source.c

使用该选项,最终生成与源文件名称相同,但是后缀为*.s结尾的汇编语言文件。

xiaomanon@xiaomanon-machine:~/Documents/c_code$ gcc -S test1.c
xiaomanon@xiaomanon-machine:~/Documents/c_code$ ls
main.c test1.c test1.s test2.c

当然,输入的源文件也不止一个,你可以编译当前目录下的所有C语言源文件:

xiaomanon@xiaomanon-machine:~/Documents/c_code$ gcc -S *.c
xiaomanon@xiaomanon-machine:~/Documents/c_code$ ls
main.c main.s test1.c test1.s test2.c test2.s

我们也可以查看生成的汇编语言代码:

 1     .file    "test1.c"
2 .text
3 .globl add
4 .type add, @function
5 add:
6 .LFB0:
7 .cfi_startproc
8 pushl %ebp
9 .cfi_def_cfa_offset 8
10 .cfi_offset 5, -8
11 movl %esp, %ebp
12 .cfi_def_cfa_register 5
13 movl 12(%ebp), %eax
14 movl 8(%ebp), %edx
15 addl %edx, %eax
16 popl %ebp
17 .cfi_restore 5
18 .cfi_def_cfa 4, 4
19 ret
20 .cfi_endproc
21 .LFE0:
22 .size add, .-add
23 .ident "GCC: (Ubuntu 4.8.2-19ubuntu1) 4.8.2"
24 .section .note.GNU-stack,"",@progbits

2.3 -c选项

  该选项(小写c)表示编译、汇编指定的源文件,但是不进行链接。该选项的使用方法如下:

gcc -c source.c

也就是在-c选项后面紧跟要编译、汇编的C源文件,最终生成与源文件名称相同,但是后缀为*.o结尾的目标文件。

xiaomanon@xiaomanon-machine:~/Documents/c_code$ ls
main.c test1.c test2.c
xiaomanon@xiaomanon-machine:~/Documents/c_code$ gcc -c test1.c
xiaomanon@xiaomanon-machine:~/Documents/c_code$ ls
main.c test1.c test1.o test2.c

可以看到,使用-c选项编译之后生成了对应的*.o目标文件。当然,你也可以一次性指定多个C源文件,使用-c选项后,会针对每一个C源文件生成一个相应的*.o目标文件。

xiaomanon@xiaomanon-machine:~/Documents/c_code$ gcc -c test2.c main.c
xiaomanon@xiaomanon-machine:~/Documents/c_code$ ls
main.c main.o test1.c test1.o test2.c test2.o

2.4 -o选项

  该选项(小写O)用于将输入文件编译后输出指定名称的文件。该选项有两种使用方法,第一种是紧跟gcc命令之后:

gcc -o app source1.c source2.c source3.c

那么,编译我们的测试程序可以使用下面的方式:

xiaomanon@xiaomanon-machine:~/Documents/c_code$ gcc -o app *.c
xiaomanon@xiaomanon-machine:~/Documents/c_code$ ls
app main.c test1.c test2.c
xiaomanon@xiaomanon-machine:~/Documents/c_code$ ./app
result = 60

还有另外一种方式,即-o选项放置在最后:

gcc source1.c source2.c source3.c -o app 

这种方式的逻辑性更强,语义可以理解为编译C语言源文件得到最终的可执行程序app,使用这种方式编译我们的测试程序过程如下:

xiaomanon@xiaomanon-machine:~/Documents/c_code$ rm app
xiaomanon@xiaomanon-machine:~/Documents/c_code$ gcc test1.c test2.c main.c -o app
xiaomanon@xiaomanon-machine:~/Documents/c_code$ ls
app main.c test1.c test2.c
xiaomanon@xiaomanon-machine:~/Documents/c_code$ ./app
result = 60

此外,此选项很多时候用作链接多个目标文件的时候,我们可能需要先对不同的源文件进行相应的操作来得到目标文件*.o,然后在最后将这些目标文件链接成一个可执行文件。

xiaomanon@xiaomanon-machine:~/Documents/c_code$ gcc -c *.c
xiaomanon@xiaomanon-machine:~/Documents/c_code$ ls
main.c main.o test1.c test1.o test2.c test2.o
xiaomanon@xiaomanon-machine:~/Documents/c_code$ gcc main.o test1.o test2.o -o app
xiaomanon@xiaomanon-machine:~/Documents/c_code$ ls
app main.c main.o test1.c test1.o test2.c test2.o
xiaomanon@xiaomanon-machine:~/Documents/c_code$ ./app
result = 60

2.5 -I选项

  该选项用于指定包含的头文件的目录,这一点对于大型的代码组织来说是很有用的。

2.6 -g选项

  该选项用来生成可以被gdb调试器使用的调试信息。只有使用了该选项后生成的可执行文件才带有程序中引用的符号表,这是gdb调试程序才能对可执行程序进行调试。

xiaomanon@xiaomanon-machine:~/Documents/c_code$ gcc *.c -o app
xiaomanon@xiaomanon-machine:~/Documents/c_code$ ll app
-rwxrwxr-x 1 xiaomanon xiaomanon 7381 12月 29 15:23 app*
xiaomanon@xiaomanon-machine:~/Documents/c_code$ gcc -g *.c -o app
xiaomanon@xiaomanon-machine:~/Documents/c_code$ ll app
-rwxrwxr-x 1 xiaomanon xiaomanon 8825 12月 29 15:23 app*

以上命令分别生成了不带调试信息的可执行文件和带有调试信息的可执行文件,并对比了两者的文件大小,可以看出使用的-g选项生成的可执行文件明显要比没有使用-g选项的可执行文件大。

GCC编译器入门[转载]的更多相关文章

  1. C语言的本质(33)——GCC编译器入门

    GCC(GNU CompilerCollection,GNU编译器套装),是由 GNU 开发的编程语言编译器.它是以GPL许可证所发行的自由软件,也是 GNU计划的关键部分.GCC原本作为GNU操作系 ...

  2. GCC编译器入门

    GCC(GNU Compiler Collection,GNU编译器套件),是由 GNU 开发的编程语言编译器.它是以GPL许可证所发行的自由软件,也是 GNU计划的关键部分.GCC原本作为GNU操作 ...

  3. GCC编译器基础入门

    导语 GCC(GNU Compiler Collection,GNU 编译器套件) 是由 GNU 开发的编程语言编译器,支持C.C++.Objective-C.Fortran.Java.Ada和Go语 ...

  4. <转载>linux gcc编译器中使用gdb单步调试程序,程序不是顺序执行的。

    原文地址http://blog.csdn.net/abc78400123/article/details/6779108 在用gdb调试,使用s 或n单步执行程序时,发现程序不是按顺序运行的,有时莫名 ...

  5. 利用GCC编译器生成动态链接库和静态链接库

    转载请标明:http://www.cnblogs.com/winifred-tang94/ 1.编译过程 gcc –fPIC –c xxx.c 其中-fPIC是通知gcc编译器产生位置独立的目标代码. ...

  6. Linux安装gcc编译器详解

    本人使用的是CentOS 6.5 64位系统,由于在安装系统的时候并没有勾选安装gcc编译器,因此需要自行安装gcc编译器. 使用yum安装gcc 对于配备了yum的Linux发行版而言,安装gcc编 ...

  7. GCC编译器使用

    一.GCC简介 通常所说的GCC是GUN Compiler Collection的简称,除了编译程序之外,它还含其他相关工具,所以它能把易于人类使用的高级语言编写的源代码构建成计算机能够直接执行的二进 ...

  8. Linux环境下的GCC编译器与GDB调试工具介绍

    假如现在我们有如下代码需要编译运行和调试.文件名为:test.c #include <stdio.h> int main() { int day, month, year, sum, le ...

  9. 在CentOS 7.2下升级gcc编译器的版本

    默认情况下,CentOS 7.2预装的gcc版本是4.8.x,通过执行命令 gcc -v 可以看到,一般情况下这个版本的编译器已经满足需要了,但是某些特殊的时候为了支持C++更高的特性,需要对gcc编 ...

随机推荐

  1. RMI 连接超时时间设定

    System.setProperty("sun.rmi.transport.tcp.responseTimeout", "2000"); System.setP ...

  2. 从 ie10浏览器下Symbol 未定义的问题 探索vue项目如何兼容ie低版本浏览器(ie9, ie10, ie 11 )

    问题:     vue项目在ie11下一片空白并报Symbol 未定义的错 原因:     ie10浏览器解析不了es6的语法,需要我们使用babel(Babel是一种工具链,主要用于将ECMAScr ...

  3. c++中sin,cos,arcsin等和在C/C++中使用pi (π) 值

    先 #include<math.h> 反3角函数有 acos(double),asin(double),atan(double),atan(double,double),返回值 doubl ...

  4. 现代 PHP 新特性系列

    生成器的创建和使用 http://laravelacademy.org/post/4317.html

  5. 在CentOS中安装输入法

    1.需要root权限,所以要用root登录 ,或su root 2.yum install "@Chinese Support" 3.exit 4.回到桌面,system-> ...

  6. spring mvc3.1 @ResponseBody注解生成大量Accept-Charset

    Spring3 MVC使用@ResponseBody后会产生非常大的响应头(Accept-Charset会达到4K+).原因在于默认情况下StringHttpMessageConverter.writ ...

  7. Java中Solr集群的测试

    import org.apache.solr.client.solrj.impl.CloudSolrServer; import org.apache.solr.common.SolrInputDoc ...

  8. commit Commit changes to stable storage 对变化提交

    Python36\site-packages\pymysql\connections.py # Python implementation of the MySQL client-server pro ...

  9. docker logspout

    https://hub.docker.com/r/jplock/rsyslog/ docker pull jplock/rsyslog:8.2.2 docker run -d -p 514:514 j ...

  10. 剑指offer 面试57题

    面试57题: 题目:和为s的数字 题目描述 输入一个递增排序的数组和一个数字S,在数组中查找两个数,是的他们的和正好是S,如果有多对数字的和等于S,输出两个数的乘积最小的.   输出描述: 对应每个测 ...