【Linux】Linux编译器gcc/g++的使用

简介: 【Linux】Linux编译器gcc/g++的使用

今天不学习,明天变垃圾。6b8318416c3f4221be922cd58832209e.jpeg



一、程序的翻译过程

1.预处理(1.2.3把你的代码编译成二进制代码)


头文件拷贝,去注释,条件编译,宏替换

-E让程序翻译到预处理阶段就停下来,-o指明形成的临时文件名称。

gcc test.c -E -o test.i
/usr/include/stdio.h //linux下的头文件路径
C:\Program Files\Microsoft Visual Studio\2022\Community\SDK\ScopeCppSDK\vc15\SDK\include\ucrt\stdio.h
//我的windows下的头文件路径


预处理之后的文件中多出来的一大堆代码其实是从linux中的/usr/include/stdio.h头文件路径下的头文件stdio.h中拷贝过来的,从头文件stdio.h中就可以找到printf函数的声明,具体的实现在C标准函数库里面

a3a33b89cc9548eb937f54814a831982.png

gcc test.c -DSHOW //标识符在命令行中定义


从下面图片便可以看出预处理阶段进行的4个步骤,删除注释,拷贝头文件,条件编译,宏替换

f9a45edf94a6446082d11794ac33819d.png


头文件最大的意义:1.写代码 2.支持代码自动补齐

2.编译(C语言 ==> 汇编语言


-S进行程序的编译工作,做完编译工作,变成汇编语言之后,就停下来!

gcc -S test.i -o test.s


3.汇编(无法被执行的二进制文件,为什么捏?)


c进行程序的汇编工作,做完汇编工作,变成可重定向目标二进制文件,就停下来!

gcc -c test.s -o test.o
od test.o //将二进制文件以二进制形式打印到显示器上


206de990700f4cc88ddd8d288a5fa95c.png

./test.o //运行二进制文件


可以看到我们无法执行这个二进制文件,其实是因为我们的文件中的一些库函数还没有成功的调用,现在仅仅只有这些库函数的声明,这些声明就在拷贝的头文件里面,而库函数的实现在标准库里面,链接阶段会帮助我们将标准库动态链接到我们的程序里面,之后程序才可以正常的运行。


4d77308210524a4daaa385a021af4514.png


最后,为了方便大家记忆指令的选项和生成的文件后缀名,这里教一下大家如何去记,ESc正好就是退出键,iso是镜像文件的后缀名


4.链接(你写的代码 + C标准库的二进制代码 ==> 生成可执行的二进制程序)

下面指令就是将我们汇编后的可重定向目标二进制文件进行链接,并且将链接过后的文件指明为mytest文件名

gcc test.o -o mytest


二、库函数调用的地方怎么与标准库关联起来的?


a.链接的本质:无非就是我们在调用库函数的时候,与标准库如何关联的这么一个问题!

b.关联的方式有两种:动态链接和静态链接


1.静态链接


链接的时候,不是与标准库产生关联,而是将程序内部要用的方法,给程序拷贝一份,这样就完成了静态链接。


优势:不受库升级或者被删除的影响,这里当然指的是形成可执行二进制程序之后不受删除的影响,如果形成之前被删除的话,拷贝也拷贝不了了。

劣势:形成的可执行程序体积太大,网络、磁盘、内存的资源占用量大,


2.动态链接


通过编译器内部的链接器,来链接标准函数库,值得注意的是,动态链接的时期是在程序运行的时候,如果程序需要链接,链接器就会链接标准函数库

优势:动态链接形成的可执行程序小,在内存、磁盘、网络等方面可以节省资源,与静态链接相比,这是决定性的优势。


3.gcc、g++、vs等默认形成的可执行程序,采用的都是动态链接

file mytest // 查看可执行程序的详细信息
ldd mytest // 查看可执行程序依赖的动态库列表


在linux下库的命名:

动态库:lib作为前缀,.so作为后缀,

静态库:lib作为前缀,.a作为后缀,

去掉前缀和后缀,剩下的就是库名称!

stdio的std就是standard标准的意思


a3a01fee29244b76b833600950a3cbe1.png

用这个库的程序非常多,但是库只有一份,所有用C语言写的程序,就不会出现重复的库代码,所以如果以后我们要下载一个C程序,还用下载C标准库吗?答案是不用的,因为我们系统里边只要有一份库就够使用了,但如果是静态链接的C程序的话,情况就不一样了,一下载就内存占用超大。


动态库默认系统里就有,静态库不一定有

静态链接,拷贝的是.a静态库的代码,所以如果想要实现静态链接,系统里就必须存在.a结尾的静态库


一般而言,为什么系统会自动携带动态库?因为光系统程序运行就需要动态库

fe20195c90bf42c784a7887cdeeb9b60.png

sudo yum install glibc-static -y // 下载c标准静态库
sudo yum install -y libstdc++-static // 下载C++标准静态库
gcc mytest.c -o mytest -static // gcc实现静态链接
g++ mytest.c -o mytest -static // g++实现静态链接


4.系统本身为了支持我们编程,给我们提供了什么呢?


系统给我们提供标准库的.h文件,这些.h文件里面有方法,它可以告诉我们怎么用这些库函数。

系统还给我们提供了动静态标准库.so/.a,这里面有方法的实现,也就是一些已经写好的二进制代码,但我们需要将我们的代码和库代码进行链接,才可以正常使用。

windows下动态库后缀为.dll静态库后缀为.lib

577745ead92f48c2a6eb4aef71d6bd50.png


在安装vs2022时,我们安装的不仅仅是编译器本身,还要安装标准库的.h文件,以及标准动静态库等

5.Linux的大部分命令就是用C语言写的


大家需要有这个认识,Linux中大部分指令都是用C语言写的。


43479b78b151452caa5ea115c718852c.png














































































































相关文章
|
1月前
|
Linux C语言
成功解决 在Linux CentOS 7 中安装gcc
这篇文章介绍了如何在Linux CentOS 7系统中安装gcc (g++) 8工具集。由于CentOS 7默认的gcc版本是4.8,而这个版本与Qt 5.14、Qt 5.15或更高版本不兼容,可能会导致编译时出现系统头文件错误。文章中提到,即使在项目配置中添加了`CONFIG+=c++11`,如果仍然报错,那么很可能是gcc版本的问题。为了解决这个问题,文章提供了使用CentOS的Software Collections (scl)来安装更新版本的gcc的步骤。
成功解决 在Linux CentOS 7 中安装gcc
|
26天前
|
Linux 编译器 C语言
Linux内核对GCC版本的检测
Linux内核对GCC版本的检测
|
1月前
|
Java Linux 编译器
【Linux】gcc简介+编译过程
【Linux】gcc简介+编译过程
|
3月前
|
Linux vr&ar C语言
Linux怎样更新Centos下Gcc版本支持C17?Centos7快速安装gcc8.3.1 可支持C++17(附gcc相关链接整理)
Linux怎样更新Centos下Gcc版本支持C17?Centos7快速安装gcc8.3.1 可支持C++17(附gcc相关链接整理)
214 2
|
3月前
|
Java 编译器 Linux
程序技术好文:详解Linux安装GCC方法
程序技术好文:详解Linux安装GCC方法
77 0
|
3月前
|
NoSQL 编译器 Linux
【Linux】--- Linux编译器-gcc/g++、调试器-gdb、项目自动化构建工具-make/Makefile 使用
【Linux】--- Linux编译器-gcc/g++、调试器-gdb、项目自动化构建工具-make/Makefile 使用
39 0
|
18天前
|
Linux Shell
Linux 中 Tail 命令的 9 个实用示例
Linux 中 Tail 命令的 9 个实用示例
59 6
Linux 中 Tail 命令的 9 个实用示例
|
14天前
|
设计模式 Java Linux
Linux的20个常用命令
Linux的23个常用命令
Linux的20个常用命令
|
23天前
|
Linux 应用服务中间件 nginx