GCC 家族无处不在

1 GCC 常用命令

1.0 引言

GCC 的意思也只是 GNU C Compiler 而已。GCC 已经不仅仅能支持 C 语言;它还支持 Ada 语言、C++ 语言、Java 语言、Objective C 语言、Pascal 语言、COBOL 语言,以及支持函数式编程和逻辑编程的 Mercury 语言,等等。而 GCC 也不再单只是 GNU C 语言编译器的意思了,而是变成了 GNU Compiler Collection 也即是 GNU 编译器家族的意思了。另一方面,说到 GCC 对于操作系统平台及硬件平台支持,概括起来就是一句话:无所不在。

接下来我们通过一个示例程序对 GCC 的常用命令进行认识,示例程序如下:

//test.c
#include<stdio.h>
int main(void)
{
	printf("Hello World!\n");
	return 0;
}

1.1 简单编译

键入命令:gcc test.c -o test,即可完成编译;接着运行完成。
在这里插入图片描述

1.2 实际编译

实质上,上述编译过程是分为四个阶段进行的,即预处理(也称预编译,Preprocessing)、编译(Compilation)、汇编(Assembly)和连接(Linking)。

(1) 预编译
键入命令:gcc -E test.c -o test.i
生成的 test.i 文件中存放着 test.c 经预处理之后的内容。
在这里插入图片描述
(2) 编译为汇编代码
键入命令:gcc -S test.i -o test.s
生成的 test.s 文件中存放着 test.i 在编译期间的生成的汇编代码内容。
在这里插入图片描述
(3) 汇编
键入命令: gcc -c test.s -o test.o
将生成的汇编代码文件 test.s,汇编器负责将其编译为目标文件。
(4) 连接
键入命令:gcc test.o -o test
将生成的 test.o,将其与C 标准输入输出库进行连接,最终生成程序 test。
在这里插入图片描述

1.3 多个程序文件的编译

(1) gcc test1.c test2.c -o test 生成的可执行文件
例如:
在这里插入图片描述
(2) 如果同时处理的文件不止一个,GCC 仍然会按照预处理、编译和链接的过程依次进行。如果深究起来,上面这条命令大致相当于依次执行如下三条命令:

gcc -c test1.c -o test1.o
gcc -c test2.c -o test2.o
gcc test1.o test2.o

例如:
在这里插入图片描述

1.4 检错

gcc -pedantic illcode.c -o illcode

-pedantic :能够帮助程序员发现一些不符合ANSI/ISO C 标准的代码,但不是全部,事实上只有 ANSI/ISO C 语言标准中要求进行编译器诊断的那些情况,才有可能被 GCC 发现并提出警告。

gcc -Wall illcode.c -o illcode GCC

-Wall :能够使 GCC 产生尽可能多的警告信息。

gcc -Werror test.c

-Werror :GCC 会在所有产生警告的地方停止编译,迫使程序员对自己的代码进行修改。

1.5 库文件连接

库文件:动态链接库(.so),静态链接库(.a)
函数库:头文件(.h),库文件(.so)

Linux 下的大多数函数都默认将头文件放到/usr/include/目录下,而库文件则放到/usr/lib/目录下。

(1) 编译

gcc –c –I /usr/dev/mysql/include test.c –o test.o

(2) 链接

gcc –L /usr/dev/mysql/lib –lmysqlclient test.o –o test

(3) 强制性使用静态链接库

gcc 链接时会优先使用动态链接库,想强制使用静态链接库执行在命令中加 -static

gcc –L /usr/dev/mysql/lib –static –lmysqlclient test.o –o test

静态链接时搜索路径顺序:
a、ld 会去找 gcc 命令中的参数-L
b、gcc 的环境变量 LBRARY_PATH(指定程序静态链接库文件的搜索路径)
c、内定目录 /lib /usr/lib /usr/local/lib
动态链接时搜索路径顺序:
a、编译目标代码时指定的动态库搜索路径
b、环境变量 LD_LIBRARY_PATH(指定程序动态链接库文件的搜索路径)
c、配置文件 /etc/ld.so.conf 中指定的动态库搜索路径
d、默认的动态库搜索路径 /lib
e、默认的动态库搜索路径 /usr/lib

2 GCC 大家族

2.1 gcc 的伙伴

GCC 不是一个人在战斗,GCC 背后其实有一堆战友。

这里进行简单介绍

工具作用
addr21line帮助调试器在调试过程中定位对应的源代码
ar用于创建静态链接库
ld用于链接
as用于汇编
ldd查看执行文件所用到的链接库
objcopy将一种对象文件翻译成另一种格式
size查看执行文件中各部分的大小
readelf查看ELF各个部分的内容
objdump进行反汇编

例如:

  • 采用动态连接库:
    在这里插入图片描述
  • 采用静态链接库:
    在这里插入图片描述
    通过上述例子也可见采用动态链接库会时执行文件小很多。

2.2 分析 ELF 文件

2.2.1 ELF 文件的段

链接器链接后生成的最终文件为 ELF 格式可执行文件,一个 ELF 可执行文件通常被链接为不同的段。位于 ELF Header 和 Section Header Table 之间的都是段。一个典型的 ELF 文件包含下面几个段:

含义
.text已编译程序的指令代码段
.rodataro 代表 read only,即只读数据(譬如常数 const )
.data已初始化的 C 程序全局变量和静态局部变量
.bss未初始化的 C 程序全局变量和静态局部变量
.debug调试符号表,调试器用此段的信息帮助调试

2.2.2 查看 ELF

键入命令: readelf -S hello
(这里用作者的 hello 文件,也可以是其他。)
在这里插入图片描述

2.2.3 反汇编ELF

由于 ELF 文件无法被当做普通文本文件打开,如果希望直接查看一个 ELF 文件包含的指令和数据,需要使用反汇编的方法。使用 objdump -D 对其进行反汇编如下:
在这里插入图片描述

  • 使用 objdump -S 将其反汇编并且将其 C 语言源代码混合显示出来:
    分别键入:
 gcc -o hello -g hello.c //要加上-g 选项
 objdump -S hello

在这里插入图片描述

3 总结

上面对 GCC 的进一步学习和了解,能认识不少与 GCC 相互协作的工具。在此基础上,也能促使更进一步了解和掌握 GCC 的灵活运用。当然,光知道了不用也不行,在你尝试过这次操作之后,希望能多多应用和思考。

4 参考资料

使用gcc和gcc的伙伴

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值