GCC 指令详解及动态库、静态库的使用一、GCC1.1 GCC 介绍GCC 是 Linux 下的编译工具集,是「GNU Compiler Collection」的缩写,包含 gcc、g++ 等编译器 。这个工具集不仅包含编译器,还包含其他工具集,例如 ar、nm 等 。
GCC 工具集不仅能编译 C/C++ 语言,其他例如 Objective-C、Pascal、Fortran、Java、Ada 等语言均能进行编译 。GCC 还可以根据不同的硬件平台进行编译,即能进行交叉编译,在 A 平台上编译 B 平台的程序 , 支持常见的 X86、ARM、PowerPC、mips 等,以及 Linux、Windows 等软件平台 。
1.2 安装 GCC首先,查看 gcc 是否安装:
# 查看 gcc 版本$ gcc -v$ gcc --version# 查看 g++ 版本$ g++ -v$ g++ --version
如果在输入指令后可以获取到 gcc 版本,那么就表明你的 Linux 中已经安装了 gcc:
文章插图
如果没有安装 , 则可按照如下方法安装 gcc:
# centos$ sudo yum update# 更新本地的软件下载列表, 得到最新的下载地址$ sudo yum install gcc g++ # 通过下载列表中提供的地址下载安装包, 并安装
1.3 GCC 工作流程1.3.1 一般使用流程首先准备一个 C 语言代码,并命名为 test.c:#include <stdio.h>#define MAX 3int main(){int i;for (i = 1; i <= MAX; i++){printf("Hello World\n"); // 输出 Hello World}return 0;}
一般情况下,我们可以直接通过 $ gcc test.c -o test
编译 test.c,并通过$ ./test
指令运行生成的可执行文件:文章插图
-o
:output,是 gcc 编译器的可选参数,用于指定输出文件名及路径,默认输出到当前路径下 。下图展示了如何通过 -o 参数修改输出路径:
文章插图
文章插图
实际上 , GCC 编译器在对程序进行编译的时候 , 分为了四个步骤:
- 预处理(Pre-Processing):
- 在这个阶段主要做了三件事:展开头文件 、宏替换 、去掉注释行
- 结果得到的还是一个 C 程序 , 通常是以 .i 作为文件扩展名
- 编译(Compiling) :
- 在这个阶段中,gcc 首先要检查代码的规范性、是否有语法错误等,以确定代码实际要做的工作
- 在检查无误后,gcc 把代码编译成汇编代码,得到一个以 .s 作为文件拓展名的汇编文件 。
- 汇编(Assembling):
+ 汇编阶段是把编译阶段生成的 .s 文件转化成目标文件+ 最终得到一个以 .o 结尾的二进制文件
- 链接(Linking):这个阶段需要 GCC 调用链接器对程序需要调用的库进行链接 , 最终得到一个可执行的二进制文件
$ gcc test.c -o test
就可以直接生成可执行文件 test 的原因 。下面我们对这 4 个步骤做个详细的介绍 。1.3.2 详细的工作流程1.3.2.1 预处理
# 通过添加参数 -E 生成预处理后的 C 文件 test.i# 必须通过 -o 参数指定输出的文件名$ gcc -E test.c -o test.i
让我们来观察一下 test.i 中的代码内容(太长了,只观察 main 函数中的替换情况):int main(){int i;for (i = 1; i <= 3; i++){printf("Hello World\n");}return 0;}
通过分析 test.i 可以发现:- 宏定义 MAX 被替换为了相应的值 3
- 注释「// 输出 Hello World」也被去掉了
# 通过添加参数 -S 将 test.i 转换为汇编文件 test.s(默认生成 .s 文件)$ gcc -S test.i$ gcc -S test.i -o test.s # 写法二
1.3.2.3 汇编# 通过汇编得到二进制文件 test.o(默认生成 .o 文件,object)$ gcc -c test.s$ gcc -c test.s -o test.o # 写法二
1.3.2.4 链接# 通过链接得到可执行文件 test$ gcc test.o -o test
在成功生成 test.o 文件后,就进入了链接阶段 。在这里涉及到一个重要的概念:函数库 。在 test.c 的代码中,我们通过
print()
函数打印 Hello World 语句;但是在这段程序中并没有定义 printf 的函数实现,且在预编译中包含进去的「stdio.h」中也只有该函数的声明extern int printf (const char *__restrict __format, ...);
,而没有定义函数的实现,那么是在哪里实现的呢?
推荐阅读
- java中GC的日志认识详解
- 我的世界指令附魔攻略(我的世界附魔1000级的指令)
- JUC中的AQS底层详细超详解
- 图文详解 微服务 Zipkin 链路追踪原理
- 唐人街探案3剧情详解_唐人街探案3讲了什么剧情
- C++之值传递&指针传递&引用传递详解
- 非常全面 Dubbo 原理和机制详解
- 未知暗殿走法路线详解(未知暗殿怎么走视频)
- JWT基础概念详解
- Go | 基本数据类型详解