news 2026/8/27 10:39:05

GCC 编译器的使用

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
GCC 编译器的使用

目录

1. 编译的四个阶段(总览)

2. 一步步手动体验(推荐亲手试)

2.1 预处理(-E)

2.2 编译(-S)

2.3 汇编(-c)

2.4 链接(-o)

3. 常用编译选项详解

4. 多文件编译的两种方式

方式一:一步到位

方式二:分开编译,统一链接(推荐大型项目)

5. 动态库(共享库)的制作与使用

5.1 制作动态库

5.2 使用动态库

5.3 运行程序

6. 静态库的制作与使用

6.1 制作静态库

6.2 使用静态库

7. 很有用的附加选项(调试与查错)

8. 交叉编译说明

9. 总结


欢迎来到 GCC 编译器的世界!如果你刚开始接触 Linux 下的 C/C++ 开发,可能会对一堆编译选项感到困惑。别担心,本文将从零开始,把 GCC 的编译过程拆成最细的步骤,每一步都配上通俗的解释和实际命令,让你不仅理解,还能自己动手操作。以后遇到编译相关的问题,也可以随时回来查阅。


1. 编译的四个阶段(总览)

一个 C/C++ 源文件变成可执行文件,需要经过预处理编译汇编链接四个步骤。每个步骤都会生成中间文件,直到最后得到可以直接运行的程序。

下面的流程图可以帮你建立直观印象:

text .c / .cpp (源代码) │ │ 预处理 (Preprocessing) ▼ .i (预处理后的文件) │ │ 编译 (Compilation) ▼ .s (汇编代码文件) │ │ 汇编 (Assembly) ▼ .o (目标文件,机器码但不可独立运行) │ │ 链接 (Linking) + 其他目标文件/库 ▼ 可执行文件 (例如 hello, a.out)

每个阶段对应的 GCC 选项:

阶段选项输入输出示例命令
预处理-Ehello.chello.igcc -E -o hello.i hello.c
编译-Shello.ihello.sgcc -S -o hello.s hello.i
汇编-chello.shello.ogcc -c -o hello.o hello.s
链接无选项(或-ohello.ohellogcc -o hello hello.o

注意:-c选项实际上是“预处理 + 编译 + 汇编”三步的合并,但不链接。而直接用gcc hello.c会完成所有四个步骤,默认生成a.out


2. 一步步手动体验(推荐亲手试)

让我们从一个最简单的hello.c文件开始,手动执行每一个步骤,看看中间文件都长什么样。

c // hello.c #include <stdio.h> #define GREETING "Hello, world!" int main() { printf("%s\n", GREETING); return 0; }

2.1 预处理(-E

预处理会做三件事:头文件展开宏替换删除注释。执行:

bash gcc -E -o hello.i hello.c

现在打开hello.i,你会看到#include <stdio.h>被替换成了几百行代码,GREETING被替换成了字符串。这个文件仍然是文本,但已经没有了宏和 #include。

2.2 编译(-S

编译将预处理后的.i文件翻译成汇编代码(人类可读的汇编语言)。执行:

bash gcc -S -o hello.s hello.i

打开hello.s,你会看到类似movl,pushq这样的指令,这是针对你当前 CPU 架构的汇编代码。

2.3 汇编(-c

汇编器将汇编代码转换成机器码(二进制),生成目标文件.o.obj)。目标文件已经是二进制了,但还不能直接运行,因为它可能还依赖其他函数(比如printf)。执行:

bash gcc -c -o hello.o hello.s

现在hello.o是一个二进制文件,可以用file hello.o查看文件类型。

2.4 链接(-o

链接器将目标文件和所需的库(比如 C 标准库)合并,生成最终的可执行文件。执行:

bash gcc -o hello hello.o

(也可以省略-o hello,默认生成a.out)。运行它:

bash ./hello

输出:Hello, world!


3. 常用编译选项详解

下面列出最实用的选项,每个都会配一个使用场景。

选项含义典型用法
-E只进行预处理,不编译、汇编、链接想查看宏展开结果:gcc -E -dM hello.c > macros.txt
-c执行预处理、编译、汇编,但不链接生成目标文件,用于后续单独链接:gcc -c -o main.o main.c
-o <file>指定输出文件名默认输出是a.out,用-o改名:gcc -o myprog main.c
-I <dir>添加头文件搜索目录#include "myheader.h"不在标准路径时:gcc -I../include -c main.c
-L <dir>添加库文件搜索目录链接时告诉链接器去哪个目录找库:gcc -o test main.o -L./libs -lmylib
-l<name>链接名为lib<name>.solib<name>.a的库链接数学库:-lm;链接自己建的库:-lmylib
-static强制静态链接生成的可执行文件不依赖动态库,体积大但移植性好:gcc -static -o hello hello.c
-v显示详细的编译过程(调试用)可以看到实际调用的子程序(cc1、as、collect2):gcc -v -o hello hello.c

4. 多文件编译的两种方式

假设你有两个源文件:main.csub.c,想生成test可执行文件。

方式一:一步到位

bash gcc -o test main.c sub.c

GCC 会自动完成所有步骤,生成最终可执行文件test

方式二:分开编译,统一链接(推荐大型项目)

bash # 分别编译成目标文件 gcc -c -o main.o main.c gcc -c -o sub.o sub.c # 链接目标文件 gcc -o test main.o sub.o

这种方式的好处是:如果只修改了main.c,只需重新编译main.o,再链接一次即可,节省时间。


5. 动态库(共享库)的制作与使用

动态库在程序运行时才被加载,多个程序可以共享一份库代码,节省内存。

5.1 制作动态库

假设有sub.csub2.csub3.c,你想把它们打包成一个动态库libsub.so

bash # 先编译成目标文件(注意:-fPIC 是位置无关代码,动态库必需) gcc -c -fPIC -o sub.o sub.c gcc -c -fPIC -o sub2.o sub2.c gcc -c -fPIC -o sub3.o sub3.c # 用 -shared 生成动态库 gcc -shared -o libsub.so sub.o sub2.o sub3.o

5.2 使用动态库

假设你的主程序main.c调用了库中的函数,编译时:

bash gcc -c -o main.o main.c gcc -o test main.o -L. -lsub
  • -L.告诉链接器在当前目录(.)查找库文件。

  • -lsub告诉链接器链接libsub.solib前缀和.so后缀自动补全)。

5.3 运行程序

动态库在程序运行时必须能被找到。有三种常见方法:

  1. 将库复制到系统标准目录(如/lib/usr/lib):

    bash sudo cp libsub.so /lib ./test
  2. 临时设置环境变量LD_LIBRARY_PATH

    bash export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:. ./test
  3. 将库路径写入可执行文件(使用-rpath链接选项,这里不展开)。


6. 静态库的制作与使用

静态库在链接时会被直接整合到可执行文件中,运行时不再需要库文件。

6.1 制作静态库

静态库本质上是多个.o文件的归档,使用ar工具创建。

bash # 先编译目标文件(静态库不需要 -fPIC) gcc -c -o sub.o sub.c gcc -c -o sub2.o sub2.c gcc -c -o sub3.o sub3.c # 用 ar 打包成静态库 libsub.a ar crs libsub.a sub.o sub2.o sub3.o

6.2 使用静态库

bash gcc -c -o main.o main.c gcc -o test main.o libsub.a

或者用-l-L选项(链接器会自动在-L路径下找libsub.a):

bash gcc -o test main.o -L. -lsub 运行程序时不需要额外的库,直接 ./test 即可。

7. 很有用的附加选项(调试与查错)

以下选项在开发中经常用来检查问题或生成辅助文件:

选项作用
gcc -E main.c只预处理并输出到屏幕,可以快速查看宏展开后的代码。
gcc -E -dM main.c > 1.txt列出文件中定义的所有宏(包括系统宏),输出到文件。
gcc -Wp,-MD,abc.dep -c -o main.o main.c生成依赖文件abc.dep(Makefile 中常用,记录头文件依赖)。
echo 'main(){}' | gcc -E -v -查看默认的头文件搜索路径、库搜索路径(非常有用)。
gcc -v -o test main.c显示完整的编译过程,包括调用的子程序。

8. 交叉编译说明

如果你的开发环境是 x86 PC,但目标机器是 ARM(例如树莓派、嵌入式设备),你需要使用交叉编译工具链,例如arm-linux-gnueabihf-gcc

用法和普通 GCC 完全一样,只是命令前缀不同:

bash arm-linux-gnueabihf-gcc -o hello hello.c # 编译 ARM 版本的可执行文件 arm-linux-gnueabihf-gcc -c -fPIC -o sub.o sub.c # 编译 ARM 的动态库目标文件

交叉编译时,特别注意头文件和库文件也必须是对应 ARM 架构的,通常通过-I-L指定交叉编译环境的 sysroot。


9. 总结

现在你应该对 GCC 的编译流程和常用选项有了清晰的认识。记住:

  • 四步走:预处理(-E)、编译(-S)、汇编(-c)、链接(无选项)。

  • 多文件:可一次编译,也可分开编译再链接。

  • :动态库(.so)运行时需要;静态库(.a)直接嵌入可执行文件。

  • 查错-v-E -dMecho ... | gcc -E -v -能帮你看到编译器的内部行为。

遇到问题就回来翻一翻,对照着命令行尝试,很快就能熟练掌握。祝编译顺利!

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/14 17:02:21

百度AI智能客服Prompt设置实战:从对话设计到性能优化全解析

最近在项目中深度使用了百度AI智能客服平台&#xff0c;深刻体会到Prompt&#xff08;提示词/指令&#xff09;设置是整个智能客服系统的“灵魂”。一个好的Prompt能让机器人对答如流&#xff0c;一个糟糕的Prompt则会让用户抓狂。今天就来系统分享一下&#xff0c;从对话设计到…

作者头像 李华
网站建设 2026/7/14 17:02:24

LangChain x PaddleOCR:重磅集成!让 AI Agents 真正看懂复杂文档

LangChain ——全球最具影响力的开源 LLM 应用工程框架之一&#xff0c;承担着模型、工具、检索与执行机制的“编排层”角色&#xff0c;为 Agent 与各类 AI Workflow 提供统一的工程基础。现在&#xff0c;LangChain 已正式集成 PaddleOCR-VL-1.5。通过全新的 PADDLEOCRVLLoad…

作者头像 李华
网站建设 2026/7/14 17:02:23

微信文件管理自动化:从混乱到有序的全流程解决方案

微信文件管理自动化&#xff1a;从混乱到有序的全流程解决方案 【免费下载链接】wxauto Windows版本微信客户端&#xff08;非网页版&#xff09;自动化&#xff0c;可实现简单的发送、接收微信消息&#xff0c;简单微信机器人 项目地址: https://gitcode.com/gh_mirrors/wx/…

作者头像 李华
网站建设 2026/7/14 17:02:24

告别视频存储焦虑:CompressO如何实现93.91%极致压缩率

告别视频存储焦虑&#xff1a;CompressO如何实现93.91%极致压缩率 【免费下载链接】compressO Convert any video into a tiny size. 项目地址: https://gitcode.com/gh_mirrors/co/compressO 在短视频创作、在线会议和远程协作成为日常的今天&#xff0c;视频文件体积过…

作者头像 李华