【Linux】基础开发工具(3):编译器

目录

[一 编译器](#一 编译器)

[1 翻译的过程(重点放在编译选项上)](#1 翻译的过程(重点放在编译选项上))

[a 预处理(进行宏替换)](#a 预处理(进行宏替换))

[b 编译](#b 编译)

[c 汇编](#c 汇编)

[d 链接](#d 链接)

[2 一般程序的构建过程(.o文件)](#2 一般程序的构建过程(.o文件))

[3 条件编译](#3 条件编译)

[4 编译器/语言的历史](#4 编译器/语言的历史)

[5 编译器和对应语言的关系:自举](#5 编译器和对应语言的关系:自举)

[6 链接](#6 链接)

(1)初步理解

(2)关于链接和指令查看:ldd关于链接和指令查看:ldd)

(3)动态库和静态库

(4)感性的理解库和链接

(5)gcc是默认动态链接

(6)两个细节


一 编译器

gcc 是 C 语言编译器,g++ 是 C++ 编译器(本质上 G++ 也能编译 C 代码,相当于将C代码转变为C++代码去进行编译,但习惯上 C 用gcc,C++ 用 g++)

编译的本质:将源文件翻译成可执行二进制文件

1 翻译的过程(重点放在编译选项上)

a 预处理(进行宏替换)

我们先在code.c中写入代码,文件包含头文件,宏,注释

如果一次性将整个代码编译完,是看不到翻译过程的

预处理指令:gcc -E code.c -o code.i:将翻译过程放到code.i的临时文件中

预处理的工作:头文件展开、去注释、宏替换、条件编译

vim code.i

code.c文件中的去注释、头文件展开、宏替换的效果都是由预处理产生的

头文件展开:就是把头文件相关内容拷贝到源文件!!头源合并的过程! (编译器只需要再预处理时需要头文件)

当我们把code.c翻译为code.i文件时,code.i还是头文件,它是一个非常干净的c语言,里面没有一个注释和宏替换

b 编译

编译 :C语言变为汇编语言

编译指令 :gcc -S code.i -o code.s

c 汇编

汇编:汇编语言变为目标文件(.o/.obj(可重定位二进制目标文件))

结束汇编时,我们不能正常运行code.o文件,还需要链接

d 链接

需要再链接的时候,把我们的.o和C标准库链接形成可执行!

链接指令: gcc code.o -o code.exe

可以这样记忆:ESc -> iso

2 一般程序的构建过程(.o文件)

gcc -c code.c:直接形成同名.o文件

提高效率:gcc -o code.exe code.o

当有很多的源文件时,先把源文件编译成.o文件,然后再把.o链接

所谓的头文件展开,就是把你include包含的头文件拷贝到你所在的源文件中,就是文件合并的过程

3 条件编译

我们在c语言的部分学过条件编译,如果忘记了我们来复习一下:

那我我们在Linux下写一段条件编译的代码:

我们发现在main函数部分,V1并没有被定义,所以编译器不会执行Version1(),会直接被编译器裁剪掉

这种方式可以由编译器在预处理阶段根据特定的条件进行代码裁剪,把这种特性叫做条件编译

预处理器可以对写的c语言代码实现增删查改的,所以预处理器就有一种能力------>可以对我的源文件做二次编辑

所以条件编译本质是文本处理

用条件编译实现不同商业化版本软件的管理

4 编译器/语言的历史

5 编译器和对应语言的关系:自举

编译器的自举是指:用目标语言(如 C++)编写的编译器,最终能编译自身源代码。这是现代编程语言(如 C++、Golang、Rust)的标准实现方式,核心解决 "如何从无到有构建目标语言编译器" 的问题。

6 链接

(1)初步理解
(2)关于链接和指令查看:ldd

ldd:查看文件依赖哪个库

关于链接:
动态库---->通常和程序进行动态链接

静态库---->通常和程序进行静态链接

(3)动态库和静态库

静态库是指编译链接时,把库文件的代码全部加入到可执行文件中,因此生成的文件比较大(大不少,前面展示过了),但在运行时也就不再需要库文件了。其后缀名一般为".a"。

动态库与之相反,在编译链接时并没有把库文件的代码加入到可执行文件中,而是在程序执行时由

运行时链接文件加载库,这样可以节省系统的开销。动态库一般后缀名为"so",如前面所述的libc.so.6就是动态库。gcc在编译时默认使用动态库。完成了链接之后,gcc就可以生成可执行文件

(4)感性的理解库和链接

动态库的小故事:

假如说你是张三,你考上了当地的一中,但是这个一中管理非常的严格,不能带手机,于是你问学长学校附近哪里有上网的地方,学长给你说学校的东门出去向左100米,向右100米,有一家电竞馆,于是你决定在学校里完成任务之后,出去上网,但是随着去电竞馆的人越来越多,电竞馆就被举报了,110就来关闭了电竞馆。

静态库的小故事:

当电竞馆因为举报关闭了之后,张三就没地方上网了,张三就给他爸说,让他爸爸从网吧老板那里买了一台电脑放到了张三的宿舍里,大家发现可以从老板那里买电脑之后,越来越多的人买了电脑回去

(5)gcc是默认动态链接
(6)两个细节

细节1:如果我删掉c动态库呢?

一般而言,系统中大部分指令(c/c++编写的二进制指令)就无法运行了

细节2:gcc默认使用动态库和动态链接

Linux系统中,默认之安装了动态库,怎么办?

我们手动安装一下静态库就可以了

# Centos

yum install glibc-static libstdc++-static -y

静态库是指编译链接时,把库文件的代码全部加⼊到可执行文件中,因此生成的文件比较大,但在运

行时也就不再需要库文件了。其后缀名⼀般为".a"

• 动态库与之相反,在编译链接时并没有把库文件的代码加入到可执行文件中,而是在程序执行时由

运行时链接文件加载库,这样可以节省系统的开销。动态库⼀般后缀名为".so",如前⾯所述的

libc.so.6就是动态库。gcc在编译时默认使用动态库 。完成了链接之后,gcc就可以生成可执行文

件,如下所示。 gcc hello.o --o hello

相关推荐
数字新视界12 分钟前
动环监控信创适配在智能机房管理中的应用价值与未来展望
大数据·服务器·数据库·动环监控系统·动力与环境监控系统
爱和冰阔落16 分钟前
【Linux网络】TCP 服务器如何并发处理多个客户端?从 fork、僵尸进程到双重 fork
linux·运维·服务器·网络
程序员沉梦听雨18 分钟前
WSL2的安装与使用
linux·wsl
微小的鱼29 分钟前
Linux的渲染与显示系统链路
android·java·linux
lisanmengmeng1 小时前
alertmanger 标签 rules 打上分组标签
linux·运维·服务器
Android系统攻城狮2 小时前
Linux FFmpeg深度解析之av_write_frame调用流程与实战(三十三)
linux·运维·服务器·ffmpeg·音视频进阶·ffmpeg音视频
上火的金鱼妹2 小时前
k8s生产实际问题排查(网关,数据库读写等)
运维·服务器
孙克旭_2 小时前
k8s基础组件与创建资源
运维·docker·容器·kubernetes
孙克旭_2 小时前
云原生基础之Containerd容器运行时
运维·云原生
分布式存储与RustFS2 小时前
RustFS 自建对象存储实战目录:110 篇按场景分类(持续更新)
运维·云原生·开源·对象存储·分布式存储·s3·性能基准