Linux入门指南:基础开发工具---gcc/g++
本文介绍了GNU编译器套件GCC的核心组件gcc和g++,详细解析了从源代码到可执行文件的完整编译流程,包括预处理、编译、汇编和链接四个关键阶段。文章对比了静态库和动态库的特性,说明了如何通过编译选项控制链接方式,并提供了多文件项目的编译方法。这些内容为理解C/C++程序的构建过程提供了基础,为后续学习Makefile和自动化构建工具奠定了基础。


目录
一.背景知识
编译器的处理过程
1.预处理
- 展开头文件
- 去注释
- 宏替换
- 条件编译
2.编译
- 将C语言翻译为汇编语言
3.汇编
- 将汇编语言翻译成为二进制文件
4.链接
- 将多个目标文件或库文件合并为最终可执行文件或共享库
二.gcc/g++的基本概念
GCC(GNU Compiler Collection)
GCC 是由 GNU 项目开发的编译器套件,支持包括 C、C++、Fortran、Ada、Go 等多种编程语言。作为开源工具集,它具备跨平台能力,可在多种操作系统和架构上运行,是许多系统和开源项目的默认编译工具,在 GCC 中,gcc 和 g++ 分别是编译 C 和 C++ 代码的核心组件
gcc
-
功能
gcc 是 GCC 套件中用于编译 C 语言代码的编译器。它将 C 源代码编译为目标代码,并调用 GCC 后端生成可执行文件或库文件
-
特点
支持 ANSI C(C89/C90)、C99、C11 等 C 语言标准,可生成与目标平台兼容的高效可执行文件
-
选项
提供丰富的编译和优化选项,如优化级别控制(
-O0/-O2)、调试信息生成(-g)、警告设置(-Wall)等
g++
-
功能
g++ 是 GCC 套件中专用于编译 C++ 代码的编译器前端,通过调用 GCC 后端生成目标代码
-
特点
全面支持 C++98、C++11、C++14、C++17 等标准,可编译符合不同规范的 C++ 代码并生成高效输出
-
选项
提供与 gcc 类似的编译控制选项,同时自动链接 C++ 标准库(如
libstdc++),支持异常处理、RTTI 等特性
其他工具
除编译器外,GCC 套件还包含:
-
预处理器:处理宏定义和文件包含(
cpp) -
汇编器:将汇编代码转为机器码(
as) -
链接器:合并目标文件生成可执行程序(
ld)
这些工具共同完成从源码到可执行文件的完整编译流程
三.gcc/g++的编译选项(以gcc为例)
验证gcc版本与安装
gcc --version

格式:
gcc [选项] 要编译的⽂件 [选项] [⽬标⽂件]
预处理
gcc -E test.c -o test.i # 预处理后形成一个.i文件


- 预处理阶段
- 选项“-E”,该选项的作用是让 gcc 在预处理结束后停止编译过程
- 选项“-o”,该选项的作用是形成一个指定名字的目标文件
- “.i”文件为已经过预处理的C原始程序
编译
gcc -S test.i -o test.s

- 在这个阶段中,gcc 首先要检查代码的规范性、是否有语法错误等,以确定代码的实际要做的工作,在检查无误后,gcc 把代码翻译成汇编语言
- 选项“-S” ,该选项的作用是只进行编译而不进行汇编,生成汇编代码

汇编
gcc -c test.s -o test.o

- 汇编阶段是把编译阶段生成的“.s”文件转成“.o”目标文件
- 选项“-c”,该选项的作用是将汇编语言翻译为可重定位二进制文件
可重定位二进制文件

链接
gcc test.o -o test # 生成可执行文件或库文件

- 在成功编译之后,就进入了链接阶段
- 链接阶段,gcc将二进制文件与函数的实现所在库进行链接,从而生成可执行文件
上述的四个过程实则为中间过程,实际在运用时,可直接将源代码编译为可执行文件:
gcc test.c -o test # gcc [目标文件] -o 要编译的文件
gcc -o test test.c # gcc -o [目标文件] 要编译的文件
编译多文件项目

gcc 要编译的文件列表 -o 目标文件

四.静态库与动态库
静态库(Static Library)
-
链接过程
静态库在编译链接阶段被直接整合到可执行文件中。链接器从库中提取被调用的函数/数据,将其机器码完整复制到最终二进制文件中 -
存储特性
每个使用静态库的可执行文件都会包含该库的独立副本,导致可执行文件体积显著增大(库代码量×程序数量),因此可执行文件体积较大 -
运行时行为
程序运行时无需外部库文件支持,所有依赖代码已硬编码在可执行文件中,实现完全自包含 -
文件规范
-
Unix/Linux系统:扩展名为 .a(如
libmath.a) -
Windows系统:扩展名为 .lib(如
openssl.lib)
-
动态库(Dynamic Library)
-
链接过程
动态库在编译阶段仅记录引用信息,实际链接推迟到程序运行时,链接器在可执行文件中写入库的路径和符号表,不复制库代码 -
存储特性
多个程序可共享同一动态库文件,磁盘和内存中只需存储一份副本,显著减少资源占用(100个程序共享1个libz.so仅需1份空间) -
运行时行为
程序启动时由动态加载器(Linux的ld.so/Windows的LoadLibrary)自动加载库到内存,若库缺失或版本不兼容会导致运行时错误(如error while loading shared libraries) -
文件规范
-
Unix/Linux系统:扩展名为 .so(如
libc.so.6) -
Windows系统:扩展名为 .dll(如
kernel32.dll)
-
如何更改gcc的链接方式
通过可执行文件的依赖库可以看到gcc的默认链接方式是链接动态库

若要让gcc的二进制程序进行静态链接,首先需要下载C/C++的静态库
sudo yum install -y glibc-static libstdc++-static
再在gcc的编译选项中选择静态链接(-static)
gcc main.c code.c -o code-static -static #-static,此选项对生成的文件强制采用静态链接

五.总结
本期介绍了 GNU 编译工具链的核心组件gcc和g++
,内容包括 GCC 工具集的整体认识、gcc与g++的具体区别、从源代码预处理、编译、汇编到链接的完整编译流程详解(包括多文件项目的处理)、以及静态库与动态库的原理、创建方法及其链接方式的选择与控制。这些知识为理解和掌握 C/C++ 程序的构建过程奠定了基础,下期我们将进一步探索项目构建自动化,详细介绍如何使用make工具和编写Makefile文件来高效地管理编译流程和项目构建任务

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。
更多推荐


所有评论(0)