本文摘录与整理于C语言中文网的相关内容,仅用于学习,如有侵权请告知删除。
原内容网址:C语言中文网:C语言程序设计门户网站(入门教程、编程软件)
GCC官方文档网址:Top (Using the GNU Compiler Collection (GCC))
1、GCC编译器的由来
谈到 GCC编译器,就不得不提 GNU 计划。GNU 计划的最终目标是打造出一套完全自由与开源的操作系统,并初步将其命名为 GNU 操作系统。虽然该计划为 GNU 操作系统量身定做了名为 Thr Hurd 的系统内核,但由于其性能比不上同时期诞生的 Linux 内核,最终 GNU 计划放弃 The Hurd 而选用 Linux 作为 GNU 操作系统的内核。因此其被称为 GNU/Linux 操作系统(人们更习惯称为 Linux 操作系统)。在 Linux 内核的基础上,GNU 计划开发了很多系统部件,GCC 就是其中之一。
早期 GCC 的全拼为 GNU C Compiler,即 GUN 计划诞生的 C 语言编译器,显然最初 GCC 的定位确实只用于编译 C 语言。但经过这些年不断的迭代,GCC 的功能得到了很大的扩展,它不仅可以用来编译 C 语言程序,还可以处理 C++、Go、Objective -C 等多种编译语言编写的程序。与此同时,由于之前的 GNU C Compiler 已经无法完美诠释 GCC 的含义,所以其英文全称被重新定义为 GNU Compiler Collection,即 GNU 编译器套件。
所谓编译器,可以简单地将其理解为“翻译器”。要知道,计算机只认识二进制指令(仅有 0 和 1 组成的指令),我们日常编写的 C 语言代码、C++ 代码、Go 代码等,计算机根本无法识别,只有将程序中的每条语句翻译成对应的二进制指令,计算机才能执行。
GCC 编译器从而停止过改进。截止到今日(2020 年 5 月),GCC 已经从最初的 1.0 版本发展到了 10.1 版本,期间历经了上百个版本的迭代。作为一款最受欢迎的编译器,GCC 被移植到数以千计的硬件/软件平台上,几乎所有的 Linux 发行版也都默认安装有 GCC 编译器,但通常版本比较低,如果需要更新,看第二点“GCC编译器下载与安装”。
操作系统大致分为 2 大阵营,分别是 Windows 阵营和类 Unix 阵营(包括 Unix、Linux、Mac OS、安卓等)。通常情况下,Windows 系统下用户更习惯使用现有的 IDE 来编译程序;而类 Unix 系统下,用户更喜欢直接编写相应的 gcc 命令来编译程序。纯 GCC 编译器没有我们熟悉的界面窗口,要想使用它必须编写对应的 gcc 命令;而集成了 GCC 编译器的开发软件(IDE),在集成 GCC 编译器功能的同时,还向用户提供友好的界面窗口,使得用户即便记不住 gcc 命令,也能从事开发工作。
2、GCC编译器下载和安装
可以在终端输入“gcc --version”查看是否已经安装GCC编译器或者版本号
root@ubuntu:/# gcc --version gcc (Ubuntu 4.8.2-19ubuntu1) 4.8.2 Copyright (C) 2013 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.root@ubuntu:/#
GCC的安装可以分为两种方式:快速安装与以源码方式手动安装。
(1)快速安装。如果对 GCC 编译器的版本没有要求,可以利用linux的软件包管理工具快速安装。采用此方式安装的 GCC 编译器,版本通常较低。(以 CentOS 的 yum 为例)
yum -y install gcc yum -y install gcc-c++
(2)以源码方式手动安装。如果需要安装指定版本的 GCC 编译器,则需要手动安装。需要到 GCC 官网下载指定版本的 GCC 源码安装包。参见:GCC编译器下载和安装教程(针对Linux发行版)
3、Sublime text在Linux下的安装
Sublime Text 是一款非常流行的文本编辑器,同时也是一个先进的代码编辑器。它最初被设计为一个具有丰富扩展功能的Vim。其界面简洁,功能强大(提供有众多的插件),还支持跨平台使用(包括 Mac OS X、Linux 和 Windows)。
这里简述Sublime text在Linux下的安装过程,参见博客:Sublime text在Linux下的安装_良知犹存的博客-CSDN博客_linux sublime
4、gcc和g++的区别
对于已编辑好 C 或者 C++ 代码,可以通过执行 gcc 或者 g++ 指令来调用 GCC 编译器。实际使用中我们更习惯使用 gcc 指令编译 C 语言程序,用 g++ 指令编译 C++ 代码。但这并不是 gcc 和 g++ 的区别,gcc 指令也可以用来编译 C++ 程序,同样 g++ 指令也可以用于编译 C 语言程序。只要是 GCC 支持编译的程序代码,都可以使用 gcc 命令完成编译。可以这样理解,gcc 是 GCC 编译器的通用编译指令,因为根据程序文件的后缀名,gcc 指令可以自行判断出当前程序所用编程语言的类别。比如:
- xxx.c:默认以编译 C 语言程序的方式编译此文件;
- xxx.cpp:默认以编译 C++ 程序的方式编译此文件。
- xxx.m:默认以编译 Objective-C 程序的方式编译此文件;
- xxx.go:默认以编译 Go 语言程序的方式编译此文件;
当然,gcc 指令也为用户提供了“手动指定代表编译方式”的接口,即使用 -x 选项。例如,gcc -xc xxx 表示以编译 C 语言代码的方式编译 xxx 文件;而 gcc -xc++ xxx 则表示以编译 C++ 代码的方式编译 xxx 文件。
但如果使用 g++ 指令,则无论目标文件的后缀名是什么,该指令都一律按照编译 C++ 代码的方式编译该文件。也就是说,对于 .c 文件来说,gcc 指令以 C 语言代码对待,而 g++ 指令会以 C++ 代码对待。但对于 .cpp 文件来说,gcc 和 g++ 都会以 C++ 代码的方式编译。
编译执行 C++ 程序,使用 gcc 和 g++ 也是有区别的。要知道,很多 C++ 程序都会调用某些标准库中现有的函数或者类对象,而单纯的 gcc 命令是无法自动链接这些标准库文件的。如果想使用 gcc 指令来编译执行 C++ 程序,需要在使用 gcc 指令时,手动为其添加 -lstdc++ -shared-libgcc 选项,表示 gcc 在编译 C++ 程序时可以链接必要的 C++ 标准库。比如:
[root@ubuntu ~]# gcc -xc++ demo.cpp -lstdc++ -shared-libgcc [root@ubuntu ~]#
简而言之,推荐使用 gcc 指令编译C程序,推荐使用 g++ 指令编译C++程序。
5、GCC的组成部分以及使用到的软件
表1列出的是GCC的组成部分。表 2 列出的软件和 GCC 协同工作,目的是实现编译过程。有些是很基本的(例如 as 和 Id),而其他一些则是非常有用但不是严格需要的。尽管这些工具中的很多都是各种 UNIX 系统的本地工具,但还是能够通过 GNU 包 binutils 得到大多数工具。
部分 | 描述 |
---|---|
c++ | gcc 的一个版木,默认语言设置为 C++,而且在连接的时候自动包含标准 C++ 库。这和 g++ 一样 |
ccl | 实际的C编译程序 |
cclplus | 实际的 C++ 编泽程序 |
collect2 | 在不使用 GNU 连接程序的系统上,有必要运行 collect2 来产生特定的全局初始化代码(例如 C++ 的构造函数和析构函数) |
configure | GCC 源代码树根目录中的一个脚木。用于设置配置值和创建GCC 编译程序必需的 make 程序的描述文件 |
crt0.o | 这个初始化和结束代码是为每个系统定制的,而且也被编译进该文件,该文件然后会被连接到每个可执行文件中来执行必要的启动和终止程序 |
cygwin1.dll | Windows 的共享库提供的 API,模拟 UNIX 系统调用 |
f77 | 该驱动程序可用于编译 Fortran |
f771 | 实际的 Fortran 编译程序 |
g++ | gcc 的一个版木,默认语言设置为 C++,而且在连接的时候自动包含标准 C++ 库。这和 c++ 一样 |
gcc | 该驱动程序等同于执行编译程序和连接程序以产生需要的输出 |
gcj | 该驱动程序用于编译 Java |
gnat1 | 实际的 Ada 编译程序 |
gnatbind | 一种工具,用于执行 Ada 语言绑定 |
gnatlink | 一种工具,用于执行 Ada 语言连接 |
jc1 | 实际的 Java 编译程序 |
libgcc | 该库包含的例程被作为编泽程序的一部分,是因为它们可被连接到实际的可执行程序中。 它们是特殊的例程,连接到可执行程序,来执行基木的任务,例如浮点运算。这些库中的例程通常都是平台相关的 |
libgcj | 运行时库包含所有的核心 Java 类 |
libobjc | 对所有 Objective-C 程序都必须的运行时库 |
libstdc++ | 运行时库,包括定义为标准语言一部分的所有的 C++ 类和函数 |
工具 | 描述 |
---|---|
addr2line | 给出一个可执行文件的内部地址,addr2line 使用文件中的调试信息将地址翻泽成源代码文 件名和行号。该程序是 binutils 包的一部分 |
ar | 这是一个程序,可通过从文档中增加、删除和析取文件来维护库文件。通常使用该工具是为了创建和管理连接程序使用的目标库文档。该程序是 binutils 包的一部分 |
as | GNU 汇编器。实际上它是一族汇编器,因为它可以被编泽或能够在各种不同平台上工作。 该程序是 binutils 包的一部分 |
autoconf | 产生的 shell 脚木自动配置源代码包去编泽某个特定版木的 UNIX |
c++filt | 程序接受被 C++ 编泽程序转换过的名字(不是被重载的),而且将该名字翻泽成初始形式。 该程序是 binutils 包的一部分 |
f2c | 是 Fortran 到C的翻译程序。不是 GCC 的一部分 |
gcov | gprof 使用的配置工具,用来确定程序运行的时候哪一部分耗时最大 |
gdb | GNU 调试器,可用于检查程序运行时的值和行为 |
GNATS | GNU 的调试跟踪系统(GNU Bug Tracking System)。一个跟踪 GCC 和其他 GNU 软件问题的在线系统 |
gprof | 该程序会监督编泽程序的执行过程,并报告程序中各个函数的运行时间,可以根据所提供 的配置文件来优化程序。该程序是 binutils 包的一部分 |
ld | GNU 连接程序。该程序将目标文件的集合组合成可执行程序。该程序是 binutils 包的一部 |
libtool | 一个基本库,支持 make 程序的描述文件使用的简化共享库用法的脚木 |
make | 一个工具程序,它会读 makefile 脚木来确定程序中的哪个部分需要编泽和连接,然后发布 必要的命令。它读出的脚木(叫做 makefile 或 Makefile)定义了文件关系和依赖关系 |
nlmconv | 将可重定位的目标文件转换成 NetWare 可加载模块(NetWare Loadable Module, NLM)。该 程序是 binutils 的一部分 |
nm | 列出目标文件中定义的符号。该程序是 binutils 包的一部分 |
objcopy | 将目标文件从一种二进制格式复制和翻译到另外一种。该程序是 binutils 包的一部分 |
objdump | 显示一个或多个目标文件中保存的多种不同信息。该程序是 binutils 包的一部分 |
ranlib | 创建和添加到 ar 文档的索引。该索引被 Id 使用来定位库中的模块。该程序是 binutils 包的一部分 |
ratfor | Ratfor 预处理程序可由 GCC 激活,但不是标准 GCC 发布版的一部分 |
readelf | 从 ELF 格式的目标文件显示信息。该程序是 binutils 包的一部分 |
size | 列出目标文件中每个部分的名字和尺寸。该程序是 binutils 包的一部分 |
strings | 浏览所有类型的文件,析取出用于显示的字符串。该程序是 binutils 包的一部分 |
strip | 从目标文件或文档库中去掉符号表,以及其他调试所需的信息。该程序是 binutils 包的一部 |
vcg | Ratfor 浏览器从文木文件中读取信息,并以图表形式显示它们。而 vcg 工具并不是 GCC 发布中的一部分,但 -dv 选项可被用来产生 vcg 可以理解的优化数据的格式 |
windres | Window 资源文件编泽程序。该程序是 binutils 包的一部分 |
6、GCC识别不同扩展名的文件
对于执行 C 或者 C++ 程序,需要借助 gcc(g++)指令来调用 GCC 编译器,并且对于以 .c 为扩展名的文件,GCC 会自动将其视为 C 源代码文件;而对于以 .cpp 为扩展名的文件,GCC 会自动将其视为 C++ 源代码文件。下面表 1 罗列了 GCC 编译器可识别的与 C 和 C++ 语言相关的文件后缀名。
如果当前文件的扩展名和表 1 不符,只需要借助 -x 选项(小写)指明当前文件的类型即可( 如果C 程序存储在无扩展名的 demo 文件中,直接使用 gcc 指令调用 GCC 编译器会报错。必须使用 -x 选项手动为其指定文件的类型,即通过为 gcc 指令添加 -xc 选项,表明当前 demo 为 C 语言程序文件,即可成功将其编译为 a.out 可执行文件)。除了用 c 表明 C 语言程序文件外,-x 指令还是后跟 c-header(C语言头文件)、c++(C++源文件)、c++-header(C++程序头文件)等选项。
[root@bogon demo]# gcc demo demo: file not recognized: File format not recognized collect2: ld returned 1 exit status [root@bogon demo]# gcc -xc demo [root@bogon demo]# ls a.out demo [root@bogon demo]# ./a.out GCC教程:http://c.biancheng.net/gcc/
文件名称+扩展名 | GCC 编译器识别的文件类型 |
---|---|
file.c | 尚未经过预处理操作的 C 源程序文件。 |
file.i | 经过预处理操作、但尚未进行编译、汇编和连接的 C 源代码文件。 |
file.cpp file.cp file.cc file.cxx file.CPP file.c++ file.C | 尚未经过预处理操作的 C++ 源代码文件。 |
file.ii | 已经预处理操作,但尚未进行编译、汇编和连接的 C++ 源代码文件。 |
file.s | 经过编译生成的汇编代码文件。 |
file.h | C、C++ 或者 Objective-C++ 语言头文件。 |
file.hh file.H file.hp file.hxx file.hpp file.HPP file.h++ file.tcc | C++ 头文件。 |
7、不同GCC版本支持的C语言编译标准
以 C 语言为例,发展至今该编程语言已经迭代了诸多个版本,例如 C89(偶尔又称为 C90)、C94(C89 的修订版)、C99、C11、C17,以及当下正在开发的 C2X 新标准。
甚至于在这些标准的基础上,GCC 编译器本身还对 C 语言的语法进行了扩展,先后产生了 GNU90、GNU99、GNU11 以及 GNU17 这 4 个版本。有趣的是,GCC 编译器对 C 语言的很多扩展,往往会被 C 语言标准委员会所采纳,并添加到新的 C 语言标准中。例如,GNU90 中对 C 语言的一些扩展,就融入到了新的 C99 标准中;GNU90、GNU99 中对 C 语言的一些扩展,被融入到了新的 C11 标准中。
C++ 语言的发展也历经了很多个版本,包括 C++98、C++03(C++98 的修订版)、C++11(有时又称为 C++0x)、C++14、C++17,以及即将要发布的 C++20 新标准。和 C 语言类似,GCC 编译器本身也对不同的 C++ 标准做了相应的扩展,比如 GNU++98、GNU++11、GNU++14、GNU++17。
不同版本的 GCC 编译器,默认使用的标准版本也不尽相同。以当前最新的 GCC 10.1.0 版本为例,默认情况下 GCC 编译器会以 GNU11 标准(C11 标准的扩展版)编译 C 语言程序,以 GNU++14 标准(C++14 标准的扩展版)编译 C++ 程序。
我们可以自由选择 GCC 编译器使用哪个编译标准。当然,这也要看该版本的GCC编译器是否支持某个编译标准,下表1和表2是不同版本的GCC编译器支持的编译标准。注意,表头表示的是各个编译标准的名称,而表格内部的则为 -std 可用的值,例如 -std=c89、-std=c11、-std=gnu90 等(表 2 也是如此)。另外,有些GCC编译器版本对应的同一编译标准有 2 种表示方式,例如对于 8.4~10.1 版本的 GCC 编译器来说,-std=c89 和 -std=c90 是一样的,使用的都是 C89/C90 标准。
对于编译 C、C++ 程序来说,借助 -std 选项即可手动控制 GCC 编译程序时所使用的编译标准。其基本格式如下:gcc/g++ -std=编译标准
[root@bogon demo]# gcc -std=c99 main.c -o main.o
GCC 版本 | C语言常用标准 | |||||||
---|---|---|---|---|---|---|---|---|
C89/C90 | C99 | C11 | C17 | GNU90 | GNU99 | GNU11 | GNU17 | |
10.1 ~ 8.4 | c89 / c90 | c99 | c11 | c17/c18 | gnu90/gnu89 | gnu99 | gnu11 | gnu17/gnu18 |
7.5 ~ 5.5 | c89/c90 | c99 | c11 | gnu90/gnu89 | gnu99 | gnu11 | ||
4.9.4 ~ 4.8.5 | c89/c90 | c99 | c11 | gnu90/gnu89 | gnu99 | gnu11 | ||
4.7.4 | c89/c90 | c99(部分支持) | c11(部分支持) | gnu90/gnu89 | gnu99(部分支持) | gnu11(部分支持) | ||
4.6.4 | c89/c90 | c99(部分支持) | c1x(部分支持) | gnu90/gnu89 | gnu99(部分支持) | gnu1x(部分支持) | ||
4.5.4 | c89/c90 | c99(部分支持) | gnu90/gnu89 | gnu99(部分支持) |
GCC 版本 | C++常用标准 | |||||||
---|---|---|---|---|---|---|---|---|
C++98/03 | C++11 | C++14 | C++17 | GNU++98 | GNU++11 | GNU++14 | GNU++17 | |
10.1 ~ 8.4 | c++98/c++03 | c++11 | c++14 | c++17 | gnu++98/gnu++03 | gnu++11 | gnu++14 | gnu++17 |
7.5 ~ 5.5 | c++98/c++03 | c++11 | c++14 | c++1z(部分支持) | gnu++98/gnu++03 | gnu++11 | gnu++14 | gnu++1z(部分支持) |
4.9.4 ~ 4.8.5 | c++98/c++03 | c++11 | c++1y(部分支持) | gnu++98/gnu++03 | gnu++11 | gnu++1y(部分支持) | ||
4.7.4 | c++98 | c++11(部分支持) | gnu++98 | gnu++11(部分支持) | ||||
4.6.4 | c++98 | c++0x(部分支持) | gnu++98 | gnu++0x(部分支持) | ||||
4.5.4 | c++98 | c++0x(部分支持) | gnu++98 | gnu++0x(部分支持) |
8、GCC编译C/C++程序(一步完成)
所谓“编译C、C++ 程序”,指的是将 C、C++ 源代码转变为可执行程序(等同 Windows 系统中以 .exe 为后缀的可执行文件)。C 或者 C++ 程序从源代码生成可执行程序的过程,需经历 4 个过程,分别是预处理、编译、汇编和链接。
GCC 编译器并未提供给用户可用鼠标点击的界面窗口,要想调用 GCC 编译器编译 C 或者 C++ 程序,只能通过执行相应的 gcc 或者 g++ 指令。使用 GCC 编译器编译 C 或者 C++ 程序,也必须要经历上述的 4 个过程。但考虑在实际使用中,用户可能并不关心程序的执行结果,只想快速得到最终的可执行程序,因此 gcc 和 g++ 都对此需求做了支持。
比如运行C文件demo.c与C++文件demo.cpp的一步完成编译的指令, GCC 编译器就会在当前目录下生成对应的可执行文件,该文件的名称为 a.out,或者使用-o 选项指定要生成的文件名。虽然仅一条指令,但依然按照预处理、编译、汇编、链接的过程将 C 、C++ 程序转变为可执行程序的。那些本应在预处理阶段、编译阶段、汇编阶段生成的中间文件,此执行方式默认是不会生成的,只会生成最终的 a.out 可执行文件(除非为 gcc 或者 g++ 额外添加 -save-temps 选项)。
[root@bogon ~]# gcc demo.c
[root@bogon ~]# g++ demo.cpp #或者 gcc -xc++ -lstdc++ -shared-libgcc demo.cpp
[root@bogon ~]# gcc demo.c -o demo.exe [root@bogon ~]# g++ demo.cpp -o democpp.exe # 或者 gcc -xc++ -lstdc++ -shared-libgcc demo.cpp -o democpp.exe
表 1 列出了实际使用 gcc 或者 g++ 指令编译 C/C++ 程序时,常用的一些指令选项。
gcc/g++指令选项 | 功 能 |
---|---|
-E(大写) | 预处理指定的源文件,不进行编译。 |
-S(大写) | 编译指定的源文件,但是不进行汇编。 |
-c | 编译、汇编指定的源文件,但是不进行链接。 |
-o | 指定生成文件的文件名。 |
-llibrary(-I library) | 其中 library 表示要搜索的库文件的名称。该选项用于手动指定链接环节中程序可以调用的库文件。建议 -l 和库文件名之间不使用空格,比如 -lstdc++。 |
-ansi | 对于 C 语言程序来说,其等价于 -std=c90;对于 C++ 程序来说,其等价于 -std=c++98。 |
-std= | 手动指令编程语言所遵循的标准,例如 c89、c90、c++98、c++11 等。 |
9、GCC分步编译C++程序
编译的四个步骤的细节知识见链接:GCC -E选项:对源程序做预处理操作。下面将以某个demo.cpp 源文件来说明如何分步编译一个C++程序。
(1)预处理
通过给 g++ 指令添加 -E 选项,可实现令 GCC 编译器只对目标源程序进行预处理操作。由于编译阶段需要用到预处理的结果,因此这里必须使用 -o 选项将该结果输出到指定的 demo.i 文件中(Linux 系统中,通常用 ".i" 或者 ".ii" 作为 C++ 程序预处理后所得文件的后缀名)。
[root@bogon demo]# g++ -E demo.cpp -o demo.i [root@bogon demo]# ls demo.cpp demo.i
(2)编译
通过给 g++ 指令添加 -S 选项,即可令 GCC 编译器仅对指定预处理文件做编译操作。对预处理文件进行编译操作,实际上就是对 demo.i 文件做进一步的语法分析,并生成对应的汇编代码文件(Linux 发行版通常以 ".s" 作为其后缀名)。即便不使用 -o 选项,编译结果也会输出到和预处理文件同名(后缀名改为 .s)的新建文件中。
[root@bogon demo]# g++ -S demo.i [root@bogon demo]# ls demo.cpp demo.i demo.s
(3)汇编
通过给 g++ 指令添加 -c 选项,即可令 GCC 编译器仅对指定的汇编代码文件做汇编操作。汇编阶段就是将之前生成的汇编代码文件(demo.s)做进一步转换,生成对应的机器指令。默认情况下汇编操作会自动生成一个和汇编代码文件名称相同、后缀名为 .o 的二进制文件(又称为目标文件)。
[root@bogon demo]# g++ -c demo.s [root@bogon demo]# ls demo.cpp demo.i demo.o demo.s
(4)链接
目标文件已经是二进制文件,与可执行文件的组织形式类似,只是有些函数和全局变量的地址还未找到,因此还无法执行。链接的作用就是找到这些目标地址,将所有的目标文件组织成一个可以执行的二进制文件。它必须把符号(变量名、函数名等一些列标识符)用对应的数据的内存地址(变量地址、函数地址等)替代,以完成程序中多个模块的外部引用。
完成链接操作并不需要给 g++ 添加任何选项,只要将汇编阶段得到的 demo.o 作为参数传递给它,g++就会在其基础上完成链接操作。(GCC 默认会链接 libc.a 或者 libc.so,但是对于其他的库,例如非标准库、第三方库等,就需要手动添加。)
在链接阶段,如果不使用 -o 选项将执行结果输出到指定文件,则会默认创建一个名为 a.out 的可执行文件,并将执行结果输出到该文件中。
[root@bogon demo]# g++ demo.o [root@bogon demo]# ls a.out demo.cpp demo.i demo.o demo.s
如果读者不想执行这么多条指令,通过给 g++ 添加 -save-temps 选项,可以使 GCC 编译器保留编译源文件过程中产生的所有中间文件。
[root@bogon demo]# g++ demo.cpp -save-temps [root@bogon demo]# ls a.out demo.c demo.cpp demo.ii demo.o demo.s
10、gcc指令一次性处理多个文件
一条 gcc(g++)指令往往可以一次性处理多个文件。
[root@bogon demo]# ls main.c myfun.c [root@bogon demo]# gcc -c myfun.c main.c [root@bogon demo]# ls main.c main.o myfun.c myfun.o [root@bogon demo]# gcc myfun.o main.o -o main.exe [root@bogon demo]# ls main.c main.exe main.o myfun.c myfun.o [root@bogon demo]# ./main.exe GCC:http://c.biancheng.net/gcc/
[root@bogon demo]# ls main.c myfun.c [root@bogon demo]# gcc *.c -o main.exe [root@bogon demo]# ls main.c main.exe myfun.c [root@bogon demo]# ./main.exe GCC:http://c.biancheng.net/gcc/