1.基本介绍
??GCC(GNU Compiler Collection )是由GNU项目产生的优化编辑器,支持各种编程语言、硬件架构和操作系统。gcc在编译程序程序时,分为以下四个阶段:预处理(Pre-Processing)、编译(Compiling)、汇编(Assembling)、链接(Linking)。
2.基本工具、命令使用
??gcc的基本用法是:gcc [options] [filenames],[options]表示参数,[filenames]表示相关文件的名称,一些最基本的参数及含义下表所示:
(1)参数汇总
表1 gcc常用参数汇总表
参数名称 | 含义 |
---|
-c | 编译程序,但不链接成为可执行文件(linux上生成后缀为 .o 的文件) | -E | 编译器经过预处理阶段后停止工作,(生成后缀为 .i 的预编译文件) | –S | 编译器经过预处理阶段后停止工作,(生成后缀为 .s 的预编译文件) | -o | 一步直接生成可执行文件 | -O/-O1/-O2/O3 | 优化代码,减少代码体积,提高代码效率,但是相应的会增加编译的时间 | -Os | 优化代码体积(注:多个-O参数默认最后一个) | -Og | 为调试代码做优化,不能与“-O”一起用 | -O0 | 关闭优化 | — | --------------------------------------------------------------------------------------------------------------------- | -w | 不输出任何警告信息 | -Wall | 将警告视为错误,编译过程一有警告便停止编译 | -g | 生成调试信息 | -v | 输出 gcc 工作的详细过程 | -ggdb | 加入GDB调试器能识别的格式 | — | -------------------------------------------------------------------------------------------------------------------- | -static | 链接静态库生成目标文件,禁止使用动态库(在支持动态链接的系统上) | -share | 尽量使用动态库,但是需要系统存在动态库,生成的目标文件较小 | -shared | 生成共享文件,然后可以与其它文件链接生成可执行文件 | -fpic | 生成适用于共享库的与地址无关的代码(PIC)(如果机器支持的话) | -fPIC | 生成与位置无关的的代码,适用于使用动态库,与“-fpic”的区别在于去除去全局偏移表的任何限制(如果机器支持的话) | -fPIE | 使用与地址无关的代码生成可执行文件 | — | -------------------------------------------------------------------------------------------------------------------- | -M | 生成适合于make规则的主要文件的依赖信息 | -MM | 与“-M”相比忽略由“#include”所造成的依赖 | -MD | 与-M作用类似,将输出导入到 .d 文件中 | -MMD | 与-MM作用类似,将输出导入到 .d 文件中 | — | ------------------------------------------------------------------------------------------------------------------- | -Wa,option | 将 option 作为选项传递给汇编器。 如果选项包含逗号,则将其在逗号处拆分为多个选项 | -Wl,option | 将 option 作为选项传递给链接器。如果选项包含逗号,则将其在逗号处拆分为多个选项。如:‘-Wl,-Map,output.map’ 传递 ‘-Map output.map’给链接器( GNU的链接器也可这样表示:‘-Wl,-Map=output.map’) | -T script | 使用script作为链接器的脚本 | -I dir | 将dir作为包含的头文件路径(-I 大写的‘i’) | -L dir | 将dir作为‘-l’(小写的’L’)操作的文件路径 |
(2)简单的例子
注:使用测试环境说明
虚拟机:VM Ware 14 ubuntu:18.04 LTS gcc版本:7.5.0 具体使用 gcc -v 命令查看如下图所示:
图1 gcc版本信息
首先我们编写一个简单的例子,输出“Hello World”:
1 #include <stdio.h>
2
3 int main(void)
4 {
5 printf("Hello World\n");
6 return 0;
7 }
然后使用 gcc -E Hello_World.c -o Hello.i 命令生成预处理文件并且使用vim查看 Hello.i 文件,其最后一部分如下图:
图2 Hello.i的最后一部分内容
然后使用 gcc -S Hello.i -o Hello.s 命令将生成的预处理文件编译成汇编程序 Hello.s,并且使用vim查看 Hello.s 的内容如下图所示:
图3 Hello.s的内容
然后使用 gcc -c Hello.s -o Hello.o 命令将生成的汇编文件编译成目标文件 Hello.o 然后使用 gcc -static Hello.o -o Hello-s 命令将生成的目标文件静态链接最终生成可执行文件 Hello-s,同时使用 gcc Hello.o -o Hello-d 命令将生成的目标文件动态链接最终生成可执行文件 Hello-d (不指定参数默认动态链接),并且分别使用 size 命令查看文件大小如下图所示:(可以看到静态链接的代码大小比动态链接大得多)
图4 动静态链接代码大小对比
分别运行 Hello-s 与 Hello-d 验证可执行文件正确性如下图所示,可以看到静态库的运行时间静态库快一点(注:使用命令:time 可查看运行时间)
图5 动静态链接代码运行时间对比
3.稍复杂一点的例子
(1)代码
(2)操作
4.总结
5.参考
|