论gcc编译工具的基本使用

一、什么是GCC编译器

GCC是由GNU开发的编程语言编译器,GNU编译器套件包括C、C++、Objective-C、Java、Ada 和 Go 语言前端,也包括了这些语言的库(如 libstdc++,libgcj等),它可以完成上述编程语言从源文件向运行在特定CPU硬件上的目标代码的转换,GCC不仅功能非常强大,而且结构也很灵活,具有良好的便携性和跨平台支持。

 

二、GCC/G++安装命令

sudo apt install gcc g++ 

安装好后可以通过以下命令来查看gcc/g++版本,确定是否安装成功

 gcc -v         # 查看gcc版本
 g++ -v         # 查看g++版本

三、GCC编译工具支持的文件类型

 

文件后缀 说明
.c C语言源程序
.a 由目标文件构成的档案库文件
.C/.cc/.cxx C++源程序
.h 源程序包含的头文件
.i C源代码文件且不应该对其执行预处理
.ii C++源代码文件且不应该对其执行预处理
.m Objective-C源程序
.o 编译后的目标文件
.s 汇编语言源代码文件
.S 经过预编译的汇编程序

四、GCC使用方法

gcc是基于Linux平台下的C语言编译器,其基本的使用语法如下。

gcc [option | fileName] [fileName] [destination fileName]

g++是基于Linux平台下的C++语言编译器,其基本的使用语法如下。

g++ [option | fileName] [fileName] [destination fileName]

 

五、GCC编译工具工作流程

gcc由C源代码文件生成可执行文件的过程不仅仅是编译的过程,而是要经历以下步骤。

gcc.drawio

这里我们以helloworld.c文件为例来阐述gcc的工作流程。

源文件代码如下:

#include <stdio.h>
#define NUM 20int main() 
{
    char s[NUM]="\0";
    printf("Please enter the content.\n");
    fgets(s, NUM, stdin);
    printf("%s", s);
    return 0;
}

(1)预处理阶段

预处理过程中,将源代码文件中包含的各种头文件以及预编译语句等展开生成后缀以.i结尾的文件。

gcc -E helloworld.c -o helloworld.i

编译生成的helloworld.i文件内容如图所示:

helloworld-i

(2)编译阶段

将预处理后以.i结尾的文件编译生成后缀以.s结尾的汇编语言代码文件。

gcc -S helloworld.i -o helloworld.s

编译生成的helloworld.s文件内容如图所示:

helloworld-s

(3)汇编阶段

将以.s为后缀的汇编语言文件经过汇编后生成后缀以.o结尾的目标文件。

gcc -c helloworld.s -o helloworld.o

编译生成的helloworld.o文件内容如图所示:

helloworld-o

打开文件我们看到其中的的内容是由各种特殊字符组成,汇编阶段的工作是将汇编语言的代码转换为机器码,这部分代码是可以直接被计算机所执行的,我们通过file helloworld.o指令查看一下该文件的类型。

helloworld.o: ELF 64-bit LSB relocatable, x86-64, version 1 (SYSV), not stripped

我们可以得知该文件的文件格式是elf格式,elf格式的文件我们可以使用readelf工具查看其中内容。

readelf -a helloworld.o

readelfhelloworld-o

(4)链接阶段

将所有源文件对应的目标文件链接起来安排在可执行程序中恰当的位置,将程序中所调用的库函数链接起来,最终生成一个可执行的程序。

gcc helloworld.o -o helloworld

在实际开发过程中,我们在编译生成可执行文件时不会一步一步执行上述命令,而是直接使用下面的命令完成预处理、编译、汇编和链接生成可执行文件。

gcc helloworld.c -o helloworld

运行结果

result

在上述的执行过程中,我们还需要知道的是,在链接阶段,链接的方式有两种,一种是静态链接,另一种是动态链接

其中静态链接是在gcc链接执行代码后面加上 --static选项,静态链接在gcc链接时就会将程序所用到的库打包到自己的可执行程序中,无需依赖外部环境,程序兼容性比较好,但是生成的程序比较大。

动态链接是在程序运行时将外部的代码库动态加载到内存中,在gcc链接时不会将代码打包到可执行程序中,生成的程序比较小。gcc的编译链接时候默认是以动态链接的方式加载的。我们可以使用ldd工具去查看动态文件的库依赖。

动态链接库依赖

我们由此可以得知通过动态链接生成的helloworld依赖于库文件linux-vdso.so.1、libc.so.6 以及ld-linux-x86-64.so.2。

我们可以分别以静态链接和动态链接的方式去编译链接上面的程序,并去查看一下两种方式生成的可执行文件的大小。

静态链接动态链接生成的文件大小对比

动态链接生成的可执行文件大小为17k,静态链接生成的可执行文件大小为852k。

六、GCC常用参数选项

 

gcc编译选项 说明
-E 预处理指定的源文件,不进行编译
-S 编译指定的源文件,但是不进行汇编
-c 编译、汇编指定的源文件,但是不进行链接
-o [file1] [file2] / [file2] -o [file1] 将文件 file2 编译成可执行文件 file1
-I directory 指定 include 包含文件的搜索目录
-g 在编译的时候,生成调试信息,该程序可以被调试器调试
-D 在程序编译的时候,指定一个宏
-w 不生成任何警告信息
-Wall 生成所有警告信息
-On n的取值范围:0~3。编译器的优化选项的4个级别,-O0表 示没有优化,-O1为缺省值,-O3优化级别最高
-l 在程序编译的时候,指定使用的库
-L 指定编译的时候,搜索的库的路径
-fPIC/fpic 生成与位置无关的代码
-shared 生成共享目标文件,通常用在建立共享库时
-std 指定C的执行版本,如:-std=c99,gcc默认的版本是GNU C
posted @   codeMario  阅读(196)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)
点击右上角即可分享
微信分享提示