博客主页:小智_x0___0x_
欢迎关注:点赞收藏✍️留言
系列专栏:Linux入门到精通
代码仓库:小智的代码仓库
我们要知道一个写一段代码到可执行程序是需要经过下面四个过程。
本篇将带大家深度探索以上的四个过程。因为gcc和g++的功能选项是一样的,本篇主要详解gcc的过程。
我们使用vim编写一个.c
文件>
gcc的使用方法:gcc + .c文件
编译完成后会生成一个a.out文件,可以看到他的文件权限中是有x(可执行权限)权限的。
我们可以输入这行指令来执行:./a.out
这样就可以执行我们的C语言程序了。
也可以使用gcc -o 可执行程序 .c文件
或者gcc .c文件 -o 可执行程序
这两个可以指定生成可执行程序的名称。
当然gcc也是可以帮我们检查语法错误的>
这里我我们故意不在后面不加;
来使用gcc编译。
可以看到下面给我们报错显示}
后面没有';'
.
mycode.c
文件>#define M 100
定义的宏gcc -E mytest.c -o mytest.i
"-E"
,该选项的作用是让 gcc 在预处理结束后停止编译过程。"-o"
是指目标文件,".i"
文件为已经过预处理的C原始程序。mytest.i
文件:shift+g
跳到末尾行。头文件的展开
预处理阶段自动把我们所包含的头文件添加进去。mytest.i
文件上面的内容都是stdio.h
中的内容。mytest.i
文件中注释被去掉了,宏定义的M
被直接替换为了100
。gcc -E mycode.c -o mycode.i -DDEBUG
这里就可以发现预处理保留了我们if条件下的语句。
我们可以通过这个指令对mycode.i
文件进行编译:gcc -S mycode.i -o mycode.s
-S的功能是从现在进行程序的翻译,将编译工作做完就停下来。
这里就生成了mycode.s
文件。我们再来打开这个文件>
".s"
文件转成目标文件。"-c"
就可看到汇编代码已转化为".o"
的二进制目标代码了。我们可以使用这行指令进行汇编处理:gcc -c mycode.s -o mycode.o
再来打开mycode.o文件(注意这里需要用od来查看文件中的内容,因为".o"文件中都是二进制机器可识别的)直接输入指令:od mycode.o
打开之后我们可以发现这里面都是二进制数,因为机器只认识二进制数(0和1)。
mycode.o
可重定位目标二进制文件,简称目标文件,(vs环境下是.obj)
不可以独立执行,虽然已经是二进制了需要经过 链接(库)
才能执行。
gcc -o mytest mycode.o
mytest
。./mytest
gcc -o mytest mycode.o
是将可重定位目标二进制文件,和库
进行链接形成可执行程序在 Linux 中,库(Library)是一组可重用的代码和数据,它们提供了一些常用的函数和方法,可以被其他程序调用。库通常被编写成共享对象文件(Shared Object File),也称为动态链接库(Dynamic Linking Library),这种文件可以在运行时被加载到内存中,并被多个程序共享。
Linux 中的库可以分为两类:
静态库(Static Library):静态库是一组预编译的对象代码,它们被链接到目标程序中,使得目标程序包含了所有所需的代码和数据。静态库的文件扩展名通常是 .a
或 .lib
。静态库的优点是使用简单,因为它们被编译到目标程序中,所以不需要在运行时加载库文件。但缺点是占用更多的磁盘空间。
动态库(Shared Library):动态库是一种动态链接库,它们被多个程序共享。共享库的文件扩展名通常是 .so
或 .dll
。共享库的优点是占用更少的磁盘空间,并且可以在多个程序之间共享代码和数据。但缺点是需要在运行时加载库文件,因此会稍微降低程序的执行速度。
Linux 中有许多常用的库,例如 C 语言标准库 libc
、数学库 libm
、图形库 libX11
等等。这些库通常都已经安装在系统中,可以直接使用。同时,开发者也可以编写自己的库,并将其发布供其他程序使用。
我们可以使用:ldd+可执行程序
来查看可执行程序所依赖的库:
libc.so.6 => /lib64/libc.so.6
是C语言的动态库。
我们也可以使用ldd
来查询Linux中的指令。
可以看到ls
指令也是依赖C语言动态库
的,这是因为Linux中大部分指令都是使用C语言编写的。
我们再来使用静态库来链接一下:gcc -o mytet_static mycode.s
可以看到动态库和静态库链接形成的两个可执行程序的大小差距还是很大的,因为静态库是将其所有内容全部拷贝过去,所以所占的字节数要大一点。(平时我们很少会使用静态库链接。)
Linux操作系统中默认是没有静态库的,我们可以使用这行指令进行安装:
sudo yum -y install glibc-static
C语言静态库安装
sudo yum install -y libstdc++-static
c++静态库安装
【注意】:
如果我们没有静态库,但是我们就要-static,行不行呢? 答案是肯定不行
如果我们没有动态库,只有静态库,而且gcc能找到 - 能的,gcc默认优先动态链接-static的本质: 改变优先级
不一定是纯的全部动态链接或者静态链接,混合的!
加了-static所有的连接要求全部变成静态链接(只适配一次)
我们也可以通过file
指令来查询可执行程序到底依赖的是哪一个库:
动态库和静态库都有各自的优缺点,下面是它们的主要特点:
动态库的优点:
动态库的缺点:
静态库的优点:
静态库的缺点:
小结:
在Linux中,Debug和Release是两种不同的编译模式,其主要区别在于编译器优化和符号表信息。
Debug模式:
Release模式:
我们默认编译生成的是release版本,如果我们想要生成debug版本可以添加一个-g选项: gcc -o mytest_debug mycode.s
。
我们可以看到debug版本比release版本所占的字节数是要大一点点的。
今天我们学习了Linux编译器gcc/g++的使用
相信大家看完有一定的收获。
种一棵树的最好时间是十年前,其次是现在!
把握好当下,合理利用时间努力奋斗,相信大家一定会实现自己的目标!加油!创作不易,辛苦各位小伙伴们动动小手,三连一波~~~
,本文中也有不足之处,欢迎各位随时私信点评指正!