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

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

GCC 常见用法

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

  • 不带任何参数的编译,会得到默认的 a.out 文件,通过 ./a.out 可以执行:
# gcc 1.c
# ./a.out
  • 可以通过 -o 输出文件名 指定生成的可执行文件名称:
# gcc -o build 1.c
# ./build
  • 可以通过 --save-temps 选项保留编译过程中产生的所有中间文件:
    各个文件的产生顺序为:.c 源文件 -> .i 预处理文件 -> .s 汇编文件 -> .o 目标对象文件 -> a.out 可执行文件。可以通过不同的选项只生成指定类型的文件。
[root@VM_139_38_centos define]# ls
main.c
[root@VM_139_38_centos define]# gcc --save-temps main.c
[root@VM_139_38_centos define]# ll
total 44
-rwxr-xr-x 1 root root  8568 Jan 19 15:32 a.out
-rw-r--r-- 1 root root   325 Jan 19 14:39 main.c
-rw-r--r-- 1 root root 16901 Jan 19 15:32 main.i
-rw-r--r-- 1 root root  1600 Jan 19 15:32 main.o
-rw-r--r-- 1 root root   561 Jan 19 15:32 main.s
  • 可以通过 -v 选项输出编译过程中产生的所有信息:
# gcc -v -o build 1.c
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/libexec/gcc/x86_64-redhat-linux/4.8.5/lto-wrapper
Target: x86_64-redhat-linux
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
Thread model: posix
gcc version 4.8.5 20150623 (Red Hat 4.8.5-28) (GCC)
COLLECT_GCC_OPTIONS='-v' '-o' 'build' '-mtune=generic' '-march=x86-64'/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
GNU C (GCC) version 4.8.5 20150623 (Red Hat 4.8.5-28) (x86_64-redhat-linux)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
GGC heuristics: --param ggc-min-expand=97 --param ggc-min-heapsize=127047
ignoring nonexistent directory "/usr/lib/gcc/x86_64-redhat-linux/4.8.5/include-fixed"
ignoring nonexistent directory "/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../x86_64-redhat-linux/include"
#include "..." search starts here:
#include <...> search starts here:/usr/lib/gcc/x86_64-redhat-linux/4.8.5/include/usr/local/include/usr/include
End of search list.
GNU C (GCC) version 4.8.5 20150623 (Red Hat 4.8.5-28) (x86_64-redhat-linux)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
GGC heuristics: --param ggc-min-expand=97 --param ggc-min-heapsize=127047
Compiler executable checksum: fbe9869a2e70aadeaf82d7c32bbeabe0
COLLECT_GCC_OPTIONS='-v' '-o' 'build' '-mtune=generic' '-march=x86-64'as -v --64 -o /tmp/ccmzAIx7.o /tmp/ccgJDXWv.s
GNU assembler version 2.25.1 (x86_64-redhat-linux) using BFD version version 2.25.1-22.base.el7
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/
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/
COLLECT_GCC_OPTIONS='-v' '-o' 'build' '-mtune=generic' '-march=x86-64'/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,例如

gcc -E -o my.i 1.c

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

编译

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

gcc -S -o my.s 1.c

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

 /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,这个选项会在汇编前自动调用编译工具。例如

gcc -c -o my.out my.s

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

链接

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

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 头文件位置 来指定要查找头文件的目录。

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

编译错误

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

链接错误

链接时缺少所需的文件

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

#include <stdio.h>void fun();int main()
{fun();return 0;
}

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

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

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

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

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

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

链接时多了所需的文件

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

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

转载于:https://www.cnblogs.com/kika/p/10851513.html

GCC 使用-C语言编译过程相关推荐

  1. C语言1066字符类型统计,C语言编译过程及数据类型

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

  2. Linux-C C语言编译过程

    Linux-C C语言编译过程 一.简述     GCC(GNU Compiler Collection,即 GNU 编译器套装),是一套由 GNU  开发的编程 语言编译器.简单介绍使用gcc编译器 ...

  3. 系统开发c语言技术参数,1 C语言 gcc 介绍 C 语言编译 main接受参数

    1 C语言 gcc 介绍 C 语言编译 main接受参数 发布时间:2020-07-19 20:18:28 来源:51CTO 阅读:1216 作者:990487026 1第一个c语言的hello wo ...

  4. C语言编译过程总结详解

    C语言的编译链接过程要把我们编写的一个c程序(源代码)转换成可以在硬件上运行的程序(可执行代码),需要进行编译和链接.编译就是把文本形式源代码翻译为机器语言形式的目标文件的过程.链接是把目标文件.操作 ...

  5. C语言编译过程中*.i *.s *.o *.out 等文件是什么?

    大家好我是大石斑Grouper,今天查资料时候看到一段鸡汤,喂大家喝一口. 皮格马利翁效应(Pygmalion Effect),又称罗森塔尔效应,即对人们的期望值越高,他们的表现就越好. 对个人而言也 ...

  6. 源代码C语言编译过程

    从源代码生成可执行文件可以分为四个步骤,分别是预处理(Preprocessing).编译(Compilation).汇编(Assembly)和链接(Linking). 下图是 GCC 生成 a.out ...

  7. Go 语言编译过程概述

    Golang 是一门需要编译才能运行的编程语言,也就说代码在运行之前需要通过编译器生成二进制机器码,随后二进制文件才能在目标机器上运行,如果我们想要了解 Go 语言的实现原理,理解它的编译过程就是一个 ...

  8. 编译是检查C语言什么的错误,c语言编译过程

    本文概述 什么是汇编? 编译是将源代码转换为目标代码的过程.这是在编译器的帮助下完成的.编译器检查源代码中的语法或结构错误,如果源代码无错误,则编译器将生成目标代码. c编译过程将作为输入的源代码转换 ...

  9. c语言将源文件拷贝到目的文件,C语言编译过程 简介和详解

    C编译的整个过程很复杂,大致可以分为以下四个阶段: 1)预处理阶段在该阶段主要完成对源代码的预处理工作,主要包括对宏定义指令,头文件包含指令,预定义指令和特殊字符的处理,如对宏定义的替换以及文件头中所 ...

最新文章

  1. dede列表分页php,dede列表页分页英文调用方法
  2. C++学习手记四:继承和多态
  3. oracle xmltype转字节,extractvalue处理XMLTYPE类型超过4000字节ORA-01706的解决方法
  4. 十年,我的计算机生涯
  5. FCPX插件Day of the Dead Titles - 恐怖风格文本动画模板
  6. 企业文件服务器(samba)配置案例一
  7. TensorBay:一款易用的像Git一样数据版本管理工具!
  8. 04,Django Form源码阅读
  9. tp3.2 生成二维码
  10. GET和POST区别详解
  11. 光纤通信(邱昆、王晟版)课后答案
  12. win7、10系统怎么设置打印机共享(打印机USB接口共享)
  13. arcgis属性字段fid修改 修改出现bad value
  14. vue3基础 —— 子传父
  15. java听课心得体会,Java初步学习的一点心得体会
  16. 只用200行Go代码写一个自己的区块链!
  17. U盘启动晨枫U盘维护工具V2.0版
  18. [转载]ExtJs4 笔记(4) Ext.XTemplate 模板
  19. 支付宝/钉钉小程序实现蓝牙打印
  20. 如何在正则表达式里表达可能存在也可能不存在的内容?

热门文章

  1. SQL基础:数据表的创建
  2. debian下tomcat8环境搭建
  3. 谈谈如何在面试中发掘程序猿的核心竞争力 什么是程序员的核心竞争力?
  4. jQuery中append、appendTo、prepend、prependTo、before、insertBefore、after与insertAfter方法注意事项...
  5. (译)如何优化cocos2d程序的内存使用和程序大小:第二部分(完)
  6. CV新赛事:密集场景行人检测
  7. 漂亮!商汤EDVR算法获NTIRE 2019 视频恢复比赛全部四项冠军,代码将开源!
  8. python如何生成一系列浮点数(含例子)
  9. 霸榜!Google发布语义分割新数据集!
  10. 论文审稿意见太奇葩?NeurIPS 2021