0

0

深度解析Linux中的编译器gcc/g++

看不見的法師

看不見的法師

发布时间:2025-04-19 09:24:06

|

389人浏览过

|

来源于php中文网

原创

gcc只用来编译c语言

g++用来编译C/C++

程序的翻译步骤经历四个过程的

1、预处理(进行宏替换/去注释/条件编译/头文件展开等)

深度解析Linux中的编译器gcc/g++

这个-E的意思是从现在开始,进行程序的翻译,一但预处理做完了,就停下来

那么这里的code.i保存的是预处理之后的结果

我们这里的-o选项就是指明了我们的生成文件的名称了

那么我们将这个code.i文件和原始的code.c进行对比下

深度解析Linux中的编译器gcc/g++

对比发现我们的源文件有24行,预处理结算的代码有800多行

我们在这个阶段进行了进行宏替换/去注释/条件编译/头文件展开等等操作

所谓的头文件展开就是将你要包含的头文件的相关内容拷贝到我们的源文件里面

2、编译(生成汇编)

输入命令gcc -S code.i -o code.s

生成了一个code.s的文件

那么这个文件里面的都是汇编语言了

这个-S的意思即是从现在开始进行程序翻译,编译做完,形成汇编,就停下来

3、汇编(生成机器可以识别的代码)

输入命令gcc -c code.s -o code.o

-c的意思是开始进行程序的翻译,汇编完成就停下来

我们生成的code.o文件是不能执行的,并且可以重定位目标二进制文件的

4、链接(生成可执行文件或者库文件)

我们的.o,库文件进行链接,然后就能进行执行的操作

我们可以通过ESc来记住这个前面三个过程的选项

那么分别形成的文件的后缀就是.iso了

如果我们出现这种情况的话,那么就是说明系统觉得我们没有权限

所以我们是需要进行配置文件的更改操作的

深度解析Linux中的编译器gcc/g++

我们需要进入到/etc/sudoers这个文件里面,我们需要使用我们的root账户,不然得话我们进去之后什么都看不见的

我们使用su切换到管理员然后进入到我们的vim模式

对文件进行修改,我们输入99gg直接跳转到第99行就行了

然后我们将root那一行进行复制

然后再粘贴到下面,将我们其他的用户名输入进去我们再输入:wq!就行了

强制保存退出

然后我们的配置文件就修改成功了

那么我们的文件就能进行文件的创建和查看的操作了

为什么我们需要进行汇编呢?

减少语言开发的成本

下面的就是编译器自举的操作

深度解析Linux中的编译器gcc/g++
动静态库和动静态库链接

库:动态库、静态库

在Linux中的动态库的文件—libXXX.so

在Linux中的静态文件----libXXX.a

在Windows中的动态库—XXXX.dill

在Windows中的动态库—XXXX.lib

如果我们使用的是gvv -c code.c的话,我们没有在后面指定上我们的文件名称的话,那么就会生成同名的.o文件

代码语言:javascript代码运行次数:0运行复制
[kk@hcss-ecs-28de lesson5]$ gcc -c code.c[kk@hcss-ecs-28de lesson5]$ ll -altotal 16drwxrwxr-x 2 kk kk 4096 Dec 27 14:49 .drwx------ 5 kk kk 4096 Dec 27 14:47 ..-rw-rw-r-- 1 kk kk   69 Dec 27 14:47 code.c-rw-rw-r-- 1 kk kk 1504 Dec 27 14:49 code.o[kk@hcss-ecs-28de lesson5]$ 
深度解析Linux中的编译器gcc/g++

前面的知识:我们的这个code.o是不能进行执行的操作的,我们是需要进行链接的

我们可以再次进行gcc code.o -o mycode的可执行文件

这个操作我们叫做链接了

一点开始链接了,那么就形成了一个mycode的文件

深度解析Linux中的编译器gcc/g++

我们使用ldd mycode来进行查看我们是否存在这个链接成功了

深度解析Linux中的编译器gcc/g++

那么我们根据这个链接找到的就是这个libc- 2.17.so

这个就是我们的C标准库

深度解析Linux中的编译器gcc/g++

gcc会帮你进行c语言的库的链接操作部

代码语言:javascript代码运行次数:0运行复制
[kk@hcss-ecs-28de lesson5]$ file mycode mycode: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=8bbc1c98d1da83282c41f5b2eca3a7a97847630a, not stripped[kk@hcss-ecs-28de lesson5]$ 
深度解析Linux中的编译器gcc/g++

这里我们可以发现我们这里的是动态链接

那么我们如何行成静态链接呢?

我们输入命令gcc code.o -o mycode -static

那么这个就是采用静态链接的方案

所以gcc默认形成的可执行程序是动态链接的

gcc -static:我们要求程序进行静态链接

我们这里如果要使用动态链接的话就要使用动态库

如果要使用静态链接的话就使用静态库

深度解析Linux中的编译器gcc/g++

需要存在对应的库,我们的Linux默认只存在动态库

Nimo.space
Nimo.space

智能画布式AI工作台

下载

sudo yum install glibc-static libstdc++-static -y我们可以使用这个命令进行静态库的安装操作

深度解析Linux中的编译器gcc/g++
深度解析Linux中的编译器gcc/g++

形成的可执行程序里面的static的体积比较大,

动态链接就是将库的地址拷贝到我们的可执行程序里面,动态库也称之为共享库

深度解析Linux中的编译器gcc/g++

动态库不能缺失,不然得话会导致所有的程序运行出错的

静态链接:将我们要的库方法实现,直接拷贝到我们的可执行程序中

所以这就是被为什么我们采用静态链接时候我们的可执行程序的大小比动态链接的时候大了

因为静态链接不再依赖任何库

我们这里的图比较形象

将我们视为可执行程序

学校视作内存

网吧视作动态库

编译器就是大哥

可执行程序和编译器产生链接,告诉我们动态库的地址信息

然后我们在内存中执行程序的时候然后执行到上网这一步了

我们直接就调用动态库了

上完了网吧回学校就是库函数调用完毕了

假如说你的同学都是可执行程序,他们都会进行调用动态库的操作,但是这个时候网吧倒闭了

就是动态库缺失了,那么我们可执行程序的就会出问题了

那么现在我们随身带上电脑,就是我们可执行程序直接将我们的库方法实现,就不用进行库函数的调用了

那么这个就是静态操作

直接将可执行程序和库方法合并起来,内存要大得多

我们可执行程序的时候默认是动态链接的,因为可执行文件的体积比较小

动态链接的优点:生成的可执行文件比较小

动态链接的缺点:一但这个库丢失了,那么我们所有的可执行文件都运行不了了

静态链接的优点:一但编译好不依赖任何库,浪费磁盘和内存空间

在 Linux 系统中,gccg++ 是 GNU 编译器集合中的核心工具,分别用于编译 C 和 C++ 程序。它们支持生成可执行文件,并且能够链接静态库和动态库。以下是关于它们以及动、静态库的详细解析。


一、GCC/G++ 的基本使用1. 编译阶段

源文件编译为目标文件:

代码语言:javascript代码运行次数:0运行复制
gcc -c file.c -o file.og++ -c file.cpp -o file.o
-c 选项表示只进行编译,不链接。生成的 .o 文件是目标文件。2. 链接阶段

目标文件链接为可执行文件:

代码语言:javascript代码运行次数:0运行复制
gcc file.o -o outputg++ file.o -o output
3. 编译并链接(一步完成)

直接编译源文件并生成可执行文件:

代码语言:javascript代码运行次数:0运行复制
gcc file.c -o outputg++ file.cpp -o output

二、Linux 动态库与静态库1. 静态库

特点:

静态库在编译时被直接嵌入到可执行文件中,生成的二进制文件是独立的。文件后缀通常为 .a

创建静态库:

代码语言:javascript代码运行次数:0运行复制
gcc -c file1.c file2.c  # 编译生成目标文件ar rcs libmylib.a file1.o file2.o  # 创建静态库
ar 是静态库管理工具。rcs 参数: r:插入文件到库中。c:创建库。s:生成符号索引表。

使用静态库:

代码语言:javascript代码运行次数:0运行复制
gcc main.c -L. -lmylib -o output
-L.:指定库所在路径。-lmylib:链接静态库 libmylib.a(注意去掉前缀 lib 和后缀 .a)。2. 动态库

特点:

动态库在运行时被加载,可执行文件依赖于动态库文件。文件后缀通常为 .so。动态库具有节省存储空间和支持共享的优点。

创建动态库:

代码语言:javascript代码运行次数:0运行复制
gcc -fPIC -c file1.c file2.c  # 编译为位置无关代码gcc -shared -o libmylib.so file1.o file2.o  # 创建动态库
-fPIC:生成位置无关代码(Position Independent Code)。-shared:指定生成共享库。

使用动态库:

代码语言:javascript代码运行次数:0运行复制
gcc main.c -L. -lmylib -o outputexport LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH  # 指定动态库路径./output
LD_LIBRARY_PATH 环境变量指定动态库的查找路径。

三、动静态库的选择

对比项

静态库

动态库

文件大小

可执行文件较大,库内容嵌入其中

可执行文件较小,运行时需要库文件支持

运行效率

加载速度更快,无需查找库文件

运行时加载,可能略慢

共享能力

不支持共享,每个程序都包含独立的副本

支持共享,多个程序可以使用同一个库

版本控制

更新库需要重新编译程序

更新库无需重新编译,但需注意兼容性


四、GCC/G++ 动静态库的链接细节1. 链接顺序

编译器按照以下顺序查找库:

指定的路径(-L 参数)。环境变量 LD_LIBRARY_PATH 中指定的路径。系统默认路径 /lib/usr/lib。2. 动态库优先级

如果同一个路径下同时存在静态库和动态库,默认优先链接动态库。

强制使用静态库:

代码语言:javascript代码运行次数:0运行复制
gcc main.c -L. -static -lmylib -o output
-static 选项强制链接静态库。3. 解决动态库版本兼容问题

动态库通常通过符号链接来管理版本:

代码语言:javascript代码运行次数:0运行复制
libmylib.so -> libmylib.so.1.0libmylib.so.1 -> libmylib.so.1.0
可执行文件加载 libmylib.so,符号链接指向具体版本。

五、工具补充

查看目标文件/库文件的符号表:

代码语言:javascript代码运行次数:0运行复制
nm file.onm libmylib.anm libmylib.so

查看动态库依赖:

代码语言:javascript代码运行次数:0运行复制
ldd output
输出依赖的动态库列表及路径。

检查动态库是否导出特定符号:

代码语言:javascript代码运行次数:0运行复制
objdump -T libmylib.so | grep symbol_name

添加动态库路径到系统默认: 将动态库路径添加到 /etc/ld.so.conf,然后运行:

代码语言:javascript代码运行次数:0运行复制
sudo ldconfig

相关专题

更多
C语言变量命名
C语言变量命名

c语言变量名规则是:1、变量名以英文字母开头;2、变量名中的字母是区分大小写的;3、变量名不能是关键字;4、变量名中不能包含空格、标点符号和类型说明符。php中文网还提供c语言变量的相关下载、相关课程等内容,供大家免费下载使用。

395

2023.06.20

c语言入门自学零基础
c语言入门自学零基础

C语言是当代人学习及生活中的必备基础知识,应用十分广泛,本专题为大家c语言入门自学零基础的相关文章,以及相关课程,感兴趣的朋友千万不要错过了。

617

2023.07.25

c语言运算符的优先级顺序
c语言运算符的优先级顺序

c语言运算符的优先级顺序是括号运算符 > 一元运算符 > 算术运算符 > 移位运算符 > 关系运算符 > 位运算符 > 逻辑运算符 > 赋值运算符 > 逗号运算符。本专题为大家提供c语言运算符相关的各种文章、以及下载和课程。

354

2023.08.02

c语言数据结构
c语言数据结构

数据结构是指将数据按照一定的方式组织和存储的方法。它是计算机科学中的重要概念,用来描述和解决实际问题中的数据组织和处理问题。数据结构可以分为线性结构和非线性结构。线性结构包括数组、链表、堆栈和队列等,而非线性结构包括树和图等。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

257

2023.08.09

c语言random函数用法
c语言random函数用法

c语言random函数用法:1、random.random,随机生成(0,1)之间的浮点数;2、random.randint,随机生成在范围之内的整数,两个参数分别表示上限和下限;3、random.randrange,在指定范围内,按指定基数递增的集合中获得一个随机数;4、random.choice,从序列中随机抽选一个数;5、random.shuffle,随机排序。

600

2023.09.05

c语言const用法
c语言const用法

const是关键字,可以用于声明常量、函数参数中的const修饰符、const修饰函数返回值、const修饰指针。详细介绍:1、声明常量,const关键字可用于声明常量,常量的值在程序运行期间不可修改,常量可以是基本数据类型,如整数、浮点数、字符等,也可是自定义的数据类型;2、函数参数中的const修饰符,const关键字可用于函数的参数中,表示该参数在函数内部不可修改等等。

524

2023.09.20

c语言get函数的用法
c语言get函数的用法

get函数是一个用于从输入流中获取字符的函数。可以从键盘、文件或其他输入设备中读取字符,并将其存储在指定的变量中。本文介绍了get函数的用法以及一些相关的注意事项。希望这篇文章能够帮助你更好地理解和使用get函数 。

640

2023.09.20

c数组初始化的方法
c数组初始化的方法

c语言数组初始化的方法有直接赋值法、不完全初始化法、省略数组长度法和二维数组初始化法。详细介绍:1、直接赋值法,这种方法可以直接将数组的值进行初始化;2、不完全初始化法,。这种方法可以在一定程度上节省内存空间;3、省略数组长度法,这种方法可以让编译器自动计算数组的长度;4、二维数组初始化法等等。

600

2023.09.22

PS使用蒙版相关教程
PS使用蒙版相关教程

本专题整合了ps使用蒙版相关教程,阅读专题下面的文章了解更多详细内容。

23

2026.01.19

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
最新Python教程 从入门到精通
最新Python教程 从入门到精通

共4课时 | 5.9万人学习

Rust 教程
Rust 教程

共28课时 | 4.6万人学习

Kotlin 教程
Kotlin 教程

共23课时 | 2.7万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号