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

今天不学习,明天变垃圾。

【Linux】Linux编译器gcc/g++的使用_第1张图片

文章目录

  • 一、程序的翻译过程
    • 1.预处理(1.2.3把你的代码编译成二进制代码)
    • 2.编译(C语言 ==> 汇编语言)
    • 3.汇编(无法被执行的二进制文件,为什么捏?)
    • 4.链接(你写的代码 + C标准库的二进制代码 ==> 生成可执行的二进制程序)
  • 二、库函数调用的地方怎么与标准库关联起来的?
    • 1.静态链接
    • 2.动态链接
    • 3.gcc、g++、vs等默认形成的可执行程序,采用的都是动态链接
    • 4.系统本身为了支持我们编程,给我们提供了什么呢?
    • 5.Linux的大部分命令就是用C语言写的



一、程序的翻译过程

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标准函数库里面

【Linux】Linux编译器gcc/g++的使用_第2张图片

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

从下面图片便可以看出预处理阶段进行的4个步骤,删除注释,拷贝头文件,条件编译,宏替换
【Linux】Linux编译器gcc/g++的使用_第3张图片

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

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

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

gcc -S test.i -o test.s

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

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

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

【Linux】Linux编译器gcc/g++的使用_第4张图片

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

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

最后,为了方便大家记忆指令的选项和生成的文件后缀名,这里教一下大家如何去记,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标准的意思

【Linux】Linux编译器gcc/g++的使用_第6张图片

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

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

一般而言,为什么系统会自动携带动态库?因为光系统程序运行就需要动态库
【Linux】Linux编译器gcc/g++的使用_第7张图片

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

【Linux】Linux编译器gcc/g++的使用_第8张图片

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

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

大家需要有这个认识,Linux中大部分指令都是用C语言写的。
【Linux】Linux编译器gcc/g++的使用_第9张图片

你可能感兴趣的:(Linux,linux,运维,服务器)