任何一种高级语言,要想在机器上执行,必须翻译为机器能读懂的机器语言。编译器就相当于翻译官,将高级语言翻译为机器语言。

GCC 最初只用了编译 C 语言程序,全称是 GNU C Compiler。后来扩展为可以编译多种语言,所以又称为 GNU Compiler Collection。GCC 是开源免费的编译器。

GCC 常见用法

GCC 是一组工具的集合,这些工具可以执行预处理、编译、汇编、链接等任务。GCC 通过文件后缀名来识别文件并调用合适的工具,例如对于 .c 文件会调用 C 编译器,对于 .cpp 文件会调用 C++ 编译器。

  • 不带任何参数的编译,会得到默认的 a.out 文件,通过 ./a.out 可以执行:
  1. # gcc 1.c
  2. # ./a.out
  • 可以通过 -o 输出文件名 指定生成的可执行文件名称:
  1. # gcc -o build 1.c
  2. # ./build
  • 可以通过 --save-temps 选项保留编译过程中产生的所有中间文件:

    各个文件的产生顺序为:.c 源文件 -> .i 预处理文件 -> .s 汇编文件 -> .o 目标对象文件 -> a.out 可执行文件。可以通过不同的选项只生成指定类型的文件。
  1. [root@VM_139_38_centos define]# ls
  2. main.c
  3. [root@VM_139_38_centos define]# gcc --save-temps main.c
  4. [root@VM_139_38_centos define]# ll
  5. total 44
  6. -rwxr-xr-x 1 root root 8568 Jan 19 15:32 a.out
  7. -rw-r--r-- 1 root root 325 Jan 19 14:39 main.c
  8. -rw-r--r-- 1 root root 16901 Jan 19 15:32 main.i
  9. -rw-r--r-- 1 root root 1600 Jan 19 15:32 main.o
  10. -rw-r--r-- 1 root root 561 Jan 19 15:32 main.s
  • 可以通过 -v 选项输出编译过程中产生的所有信息:
  1. # gcc -v -o build 1.c
  2. Using built-in specs.
  3. COLLECT_GCC=gcc
  4. COLLECT_LTO_WRAPPER=/usr/libexec/gcc/x86_64-redhat-linux/4.8.5/lto-wrapper
  5. Target: x86_64-redhat-linux
  6. Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=http://bugzilla.redhat.com/bugzilla --enable-bootstrap --enable-shared --enable-threads=posix --enable-checking=release --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-gnu-unique-object --enable-linker-build-id --with-linker-hash-style=gnu --enable-languages=c,c++,objc,obj-c++,java,fortran,ada,go,lto --enable-plugin --enable-initfini-array --disable-libgcj --with-isl=/builddir/build/BUILD/gcc-4.8.5-20150702/obj-x86_64-redhat-linux/isl-install --with-cloog=/builddir/build/BUILD/gcc-4.8.5-20150702/obj-x86_64-redhat-linux/cloog-install --enable-gnu-indirect-function --with-tune=generic --with-arch_32=x86-64 --build=x86_64-redhat-linux
  7. Thread model: posix
  8. gcc version 4.8.5 20150623 (Red Hat 4.8.5-28) (GCC)
  9. COLLECT_GCC_OPTIONS='-v' '-o' 'build' '-mtune=generic' '-march=x86-64'
  10. /usr/libexec/gcc/x86_64-redhat-linux/4.8.5/cc1 -quiet -v 1.c -quiet -dumpbase 1.c -mtune=generic -march=x86-64 -auxbase 1 -version -o /tmp/ccgJDXWv.s
  11. GNU C (GCC) version 4.8.5 20150623 (Red Hat 4.8.5-28) (x86_64-redhat-linux)
  12. compiled by GNU C version 4.8.5 20150623 (Red Hat 4.8.5-28), GMP version 6.0.0, MPFR version 3.1.1, MPC version 1.0.1
  13. GGC heuristics: --param ggc-min-expand=97 --param ggc-min-heapsize=127047
  14. ignoring nonexistent directory "/usr/lib/gcc/x86_64-redhat-linux/4.8.5/include-fixed"
  15. ignoring nonexistent directory "/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../x86_64-redhat-linux/include"
  16. #include "..." search starts here:
  17. #include <...> search starts here:
  18. /usr/lib/gcc/x86_64-redhat-linux/4.8.5/include
  19. /usr/local/include
  20. /usr/include
  21. End of search list.
  22. GNU C (GCC) version 4.8.5 20150623 (Red Hat 4.8.5-28) (x86_64-redhat-linux)
  23. compiled by GNU C version 4.8.5 20150623 (Red Hat 4.8.5-28), GMP version 6.0.0, MPFR version 3.1.1, MPC version 1.0.1
  24. GGC heuristics: --param ggc-min-expand=97 --param ggc-min-heapsize=127047
  25. Compiler executable checksum: fbe9869a2e70aadeaf82d7c32bbeabe0
  26. COLLECT_GCC_OPTIONS='-v' '-o' 'build' '-mtune=generic' '-march=x86-64'
  27. as -v --64 -o /tmp/ccmzAIx7.o /tmp/ccgJDXWv.s
  28. GNU assembler version 2.25.1 (x86_64-redhat-linux) using BFD version version 2.25.1-22.base.el7
  29. COMPILER_PATH=/usr/libexec/gcc/x86_64-redhat-linux/4.8.5/:/usr/libexec/gcc/x86_64-redhat-linux/4.8.5/:/usr/libexec/gcc/x86_64-redhat-linux/:/usr/lib/gcc/x86_64-redhat-linux/4.8.5/:/usr/lib/gcc/x86_64-redhat-linux/
  30. LIBRARY_PATH=/usr/lib/gcc/x86_64-redhat-linux/4.8.5/:/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../lib64/:/lib/../lib64/:/usr/lib/../lib64/:/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../:/lib/:/usr/lib/
  31. COLLECT_GCC_OPTIONS='-v' '-o' 'build' '-mtune=generic' '-march=x86-64'
  32. /usr/libexec/gcc/x86_64-redhat-linux/4.8.5/collect2 --build-id --no-add-needed --eh-frame-hdr --hash-style=gnu -m elf_x86_64 -dynamic-linker /lib64/ld-linux-x86-64.so.2 -o build /usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../lib64/crt1.o /usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../lib64/crti.o /usr/lib/gcc/x86_64-redhat-linux/4.8.5/crtbegin.o -L/usr/lib/gcc/x86_64-redhat-linux/4.8.5 -L/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../lib64 -L/lib/../lib64 -L/usr/lib/../lib64 -L/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../.. /tmp/ccmzAIx7.o -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed /usr/lib/gcc/x86_64-redhat-linux/4.8.5/crtend.o /usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../lib64/crtn.o

C 语言编译过程

预处理

预处理时,会把所有的 include 替换为所引入文件的代码,把 define 宏定义都替换为具体的定义元素。对 C 程序预处理后,得到 .i 文件。对应 GCC 的选项是 gcc -E,例如

  1. gcc -E -o my.i 1.c

命令可以得到 my.i 这个文件。

编译

对 C 程序编译后,得到汇编程序。对应 GCC 的选项是 gcc -S,例如

  1. gcc -S -o my.s 1.c

命令可以得到 my.s 这个汇编文件。这个步骤对应上面的输出信息为:

  1. /usr/libexec/gcc/x86_64-redhat-linux/4.8.5/cc1 -quiet -v 1.c -o /tmp/ccgJDXWv.s -quiet -dumpbase 1.c -mtune=generic -march=x86-64 -auxbase 1 -version

汇编

将上一步编译得到的汇编程序,转为 .o 输出文件,这是可以被计算机直接读懂的二进制文件。但是需要注意,因为没有链接进额外的资源,通常这个文件是不能直接执行的。对应 GCC 的选项是 gcc -c,这个选项会在汇编前自动调用编译工具。例如

  1. gcc -c -o my.out my.s

命令可以得到 my.out 这个输出文件,此时还需要链接,还不能直接执行。

链接

链接,可以将多个 .o 输出文件组成一个可执行文件,可以自动链接所需的依赖。例如

  1. gcc -o myExe my.out

对应 GCC 的选项是 gcc -o,如果指定的输入是 .c 或 .s 后缀的文件,这个选项在链接前会自动调用编译或/和汇编两个工具。

通常使用 GCC 时,直接调用 gcc -o myOutName xx.c yy.c zz.c 即可自动完成上述所有步骤,得到一个可执行文件。

C 语言编译时的常见错误

预处理错误

C 语言有两种方式引入头文件:

  • 双引号 “”:例如 #include "my.h",首先在当前目录下寻找,找不到的话再去系统库中寻找。用于自己实现的头文件。
  • 尖括号 <>:例如 #include <stdio.h>,直接在系统库中寻找。

项目中通常把头文件放在单独的目录中,例如项目根目录下的 inc 目录。这时可用在使用 GCC 时通过 -I 头文件位置 来指定要查找头文件的目录。

  1. [root@VM_139_38_centos header]# gcc main.c
  2. main.c:2:16: fatal error: my.h: No such file or directory
  3. #include "my.h"
  4. ^
  5. compilation terminated.
  6. [root@VM_139_38_centos header]# gcc -I inc main.c
  7. [root@VM_139_38_centos header]# ./a.out
  8. Hello World! 123

编译错误

编译错误主要是语法错误。例如括号不配对,变量名写错。

链接错误

链接时缺少所需的文件

链接时发现缺少所需的文件,例如函数定义缺失,会报链接错误。例如对下面的代码:

  1. #include <stdio.h>
  2. void fun();
  3. int main()
  4. {
  5. fun();
  6. return 0;
  7. }

编译时会有如下报错,其中 collect2 命令是链接时用的程序:

  1. /tmp/cc2lEZt4.o: In function `main':
  2. main.c:(.text+0x15): undefined reference to `fun'
  3. collect2: error: ld returned 1 exit status

解决方法也很简单,在同一个文件中实现这个方法后,重新编译即可。如果方法的实现在另一个文件中,可以在用 GCC 编译时指定这个文件即可,例如方法声明在 1.c 中,而方法体在 2.c 这个文件中,则用下面的命令编译即可:

  1. gcc -o my.out 1.c 2.c

当然,通常每个文件都是单独编译的,最后链接到一起:

  1. gcc -c -o 1.o 1.c
  2. gcc -c -o 2.o 2.c
  3. gcc -o my.out 1.o 2.o

链接时多了所需的文件

例如,一个方法在多个文件中定义,而链接时需要把这几个文件整合为一个可执行文件,就会报错:

  1. fun.o: In function `fun':
  2. fun.c:(.text+0x0): multiple definition of `fun'
  3. main.o:main.c:(.text+0x0): first defined here
  4. collect2: error: ld returned 1 exit status

GCC 使用-C语言编译过程的更多相关文章

  1. C语言编译过程以及gcc编译参数

    1.1       C语言编译过程,gcc参数简介 1.1.1          C语言编译过程 一.gcc - o a a.c -o:指定文件输出名字 二.C语言编译的过程: 1.1.1       ...

  2. C语言编译过程及数据类型

    写在前面 C语言可以称得上是高级语言中的低级语言,接下来一段时间,我会写一下文章关于c语言,把它的神秘面纱一 一揭开.下面主要是c语言的C语言编译过程及数据类型 源文件编译过程 为了使计算机能执行高级 ...

  3. 转 C语言编译过程简介

    C语言编译过程简介 C语言编译过程简介 刚开始接触编程的时候,只知道照书敲敲代码,一直都不知道为什么在windows平台下代码经过鼠标那样点击几下,程序的结果就会在那个黑色的屏幕上.现在找了个机会将C ...

  4. Go 语言编译过程

    走进Golang之编译器原理_大愚Talk-CSDN博客 https://blog.csdn.net/hel12he/article/details/103061921 go编译器 - 知乎 http ...

  5. go语言编译过程概述

    go语言编译过程概述 总结自<go语言设计与实现> 名词解释: 中间代码 中间代码是编译器或者虚拟机使用的语言,它可以来帮助我们分析计算机程序.在编译过程中,编译器会在将源代码转换到机器码 ...

  6. C语言基础(21)-C语言编译过程及GCC参数简介

    任何C语言的编译过程可分为以下三部分: 一.预编译 在C语言中,以#开头的语句又叫预编译指令.预编译主要做以下两件事情: 1.将#include包含的头文件做简单的文本替换: 2.将代码中的注释删除. ...

  7. 忙里偷闲( ˇˍˇ )闲里偷学【C语言篇】——(1)GCC介绍及C语言编译过程

    一.GCC基本介绍 GCC(GNU Compiler Collection,GNU编译器套装),是一套由GNU开发的编程语言编译器.它是一套以GPL及LGPL许可证所发布的自由软件,也是GNU计划的关 ...

  8. C语言编译过程以及Windows中的gcc编译程序(通过cmd、记事本)

    C语言的编译过程 1)预处理:宏定义展开.头文件展开.条件编译等,同时将代码中的注释删除,这里并不会检查语法 2)编译:检查语法,将预处理后的文件编译生成汇编文件 3)汇编:将汇编文件生成目标文件(二 ...

  9. GCC 概述:C 语言编译过程详解

    Tags: C Description: 关于 GCC 的个人笔记 GCC 概述 对于 GCC 6.1 以及之后的版本,默认使用的 C++ 标准是 C++ 14:使用 -std=c++11 来指定使用 ...

随机推荐

  1. scp 从另一台linux服务器拷贝文件或文件目录

    格式:scp [参数] [原路径] [目标路径] download 使用方法:scp -r root@127.0.0.1:/opt/soft/test /opt/soft/ scp -r 用户名@IP ...

  2. ROPE

    #include <ext/rope> using namespace __gnu_cxx; ]; rope<int> x; rope<int> x(a,a + n ...

  3. Tableau Dashboard

    Dashboard仪表盘,用来展示多个图表,并展示之间的联动,分析数据.

  4. MVC-MVP-MVVM框架模式分析

    MVC(Model-View-Controller) MVC 架构模式图(经典版) 注:实际上,Model和View永远不能相互通信,只能通过Controller传递:上图只是MVC模式的经典图. M ...

  5. 深入理解JAVA虚拟机 程序编译和代码优化

    泛型类型擦除 C#中的泛型,不论是代码中,还是编译后,还是运行期,都是切实存在的.List<String>和List<Int>是两个截然不同的类型,有自己的虚方法表和类型数据, ...

  6. SpringMVC @CookieValue注解

    @CookieValue的作用 用来获取Cookie中的值 @CookieValue参数 1.value:参数名称 2.required:是否必须 3.defaultValue:默认值 @Cookie ...

  7. Django报错 No module named 'django.templates'

    前言 Django 模板报错了 修改方法: 将你的工程文件下(my_site)的settings.py中的TEMPLATES中的templates字段全部改为template, 亲测可用~^~

  8. thinkphp查询构造器和链式操作、事务

    插入 更新记录 查询数据 删除数据 插入数据----name这种用法,会去config.php中去寻找前缀,如果你定义了前缀tp,那么执行下条语句会查询对tp_data的插入操作 链式操作---> ...

  9. es6 Object.assign(target, ...sources)

    Object.assign() 方法用于将所有可枚举属性(对象属性)的值从一个或多个源对象复制到目标对象.它将返回目标对象. 语法 Object.assign(target, ...sources) ...

  10. Error: pgraster_wkb_reader: grayscale band type 10 unsupported

    错误原因:Float32 is not supported for rendering.即栅格数据类型Float32不支持. cmd中用GDAL查看.在波段中的数据类型是Float32的不支持渲染. ...