Linux系统应用(5)——编译器gcc

个人内容简介:

🍃个人主页:诉清风2023

🎈逆转时间的公式,就是珍惜现在ദ്ദി˶ー̀֊ー́ ) ✧


目录

个人内容简介:

🎈逆转时间的公式,就是珍惜现在ദ്ദി˶ー̀֊ー́ ) ✧ ✧)

前言

1、预处理

2、编译

3、汇编

4、链接

5、gcc选项

6、函数库

[6.1 静态库](#6.1 静态库)

[6.2 动态库](#6.2 动态库)

结语


前言

重点

在软件开发的过程中,从源代码到可执行程序的转变是一个复杂且有序的过程,通常包括预处理(Preprocessing)、编译(Compilation)、汇编(Assembly)和链接(Linking)几个阶段

注意

这部分内容并没有难度,只需要理解和会使用即可


1、预处理

补充:gcc格式

gcc [选项] 要编译的文件 [选项] [目标文件]
预处理是编译过程的第一步,它处理源代码文件中的预处理指令(以#开头的指令)。预处理器的任务主要包括:

  • 宏定义(Macro Definition) :处理#define指令,将宏名称替换为其定义的内容。
  • 条件编译(Conditional Compilation) :通过#ifdef#ifndef#endif等指令,根据条件包含或排除代码段。
  • 文件包含(File Inclusion) :通过#include指令将其他文件的内容插入到当前文件中。
  • 行控制和错误消息生成 :使用#line指令控制编译器的错误和警告信息的行号,使用#error#warning生成错误和警告消息。

预处理后的结果是一个纯净的源代码文件,但其中已经包含了所有宏替换和文件包含的结果。

复制代码
gcc --E code.c --o code.i
//选项"-E",该选项的作用是让 gcc 在预处理结束后停止编译过程。
//选项"-o"是指目标文件,".i"文件为已经过预处理的C原始程序。

2、编译

编译是将预处理后的源代码文件转换成汇编代码的过程。编译器的主要任务包括:

  • 词法分析(Lexical Analysis):将源代码分解成一系列的标记(tokens)。
  • 语法分析(Syntax Analysis):根据语言的语法规则分析标记,构建语法树(Syntax Tree)。
  • 语义分析(Semantic Analysis):检查语法树中表达式的意义,进行类型检查等。
  • 中间代码生成(Intermediate Code Generation):将语法树转换成一种中间表示(Intermediate Representation, IR),便于后续处理。
  • 代码优化(Code Optimization):对中间代码进行优化,以提高代码执行效率。
  • 目标代码生成(Target Code Generation):将优化后的中间代码转换成目标机器的汇编代码。
复制代码
gcc --S code.i --o code.s
//选项"-S",该选项的作用是让 gcc 在编译结束后停止汇编过程。
//选项"-o"是指目标文件,".s"文件为已经过预处理和编译的C程序

3、汇编

汇编是将汇编代码转换成机器代码的过程。汇编器(Assembler)读取汇编代码,并将其转换为特定机器的机器语言指令。++机器代码是计算机可以直接执行的代码。++

复制代码
gcc --C code.s --o code.o
//选项"-C",该选项的作用是让 gcc 在汇编结束后停止链接过程。
//选项"-o"是指目标文件,".o"文件为已经过预处理、编译和汇编的C程序

4、链接

链接是++将多个编译后的机器代码文件(以及库文件)合并成一个可执行文件或库文件的过程++。链接器的任务主要包括:

  • **地址和空间分配 :**为程序中的变量和函数分配内存地址。
  • **符号解析(Symbol Resolution):**解析程序中的符号引用,即确定程序中调用的函数或引用的变量在内存中的位置。
  • **重定位(Relocation):**修改代码和数据中的地址,以反映它们在内存中的最终位置。
  • **生成可执行文件或库文件 :**将多个对象文件合并,并可能包括一些运行时库,最终生成可执行文件或库文件。

这四个阶段共同构成了从源代码到可执行程序的完整开发流程。在现代开发环境中,这些步骤通常由构建系统(如Make、CMake、Maven等)自动化完成。

复制代码
gcc code.o --o code
//选项"-o"是指目标文件,code为最后的可执行程序

5、gcc选项

  • -E 只++激活预处理++,这个不生成文件,你需要把它重定向到一个输出文件里面
  • -S 编译到汇编语言不进行汇编和链接
  • -c 编译到目标代码
  • -o文件输出到文件
  • -static此选项对生成的文件采用静态链接
  • -g生成调试信息。GNU 调试器可利用该信息。
  • -shared 此选项将尽量使用动态库,所以生成文件比较小,但是需要系统由动态库.
  • -O0
  • -O1
  • -O2
  • -O3编译器的优化选项的4个级别,-O0表示没有优化,-O1为缺省值,-O3优化级别最高
  • -w不生成任何警告信息。
  • -Wall 生成所有警告信息。

6、函数库

我们的C程序中,并没有定义"printf"的函数实现,且在预编译中包含的"stdio.h"中也只有该函数的声明,而没有定义函数的实现,那么,是在哪里实"printf"函数的呢?

最后的答案是:系统把这些函数实现都被做到名为 libc.so.6 的库文件中去了,在没有特别指定时,gcc 会到系统默认的搜索路径**"/usr/lib"** 下进行查找,也就是链接到 libc.so.6库函数中去,这样就能实现函数"printf"了, 而这也就是链接的作用。

6.1 静态库

静态库是指编译链接时,把库文件的代码全部加入到可执行文件中,因此生成的文件比较大,但在运行时也就 不再需要库文件了。

其后缀名一般为".a"

注意:

++如果在编译过程中敲静态编译的指令报错后,检查是否是因为未安装静态库++

静态库安装方法:

复制代码
sudo yum -y install glibc-static
//静态库安装方法

gcc -o code_static code.c -static
//静态库编译链接

6.2 动态库

动态库与之相反,在编译链接时并没有把库文件的代码加入到可执行文件中,而是在程序执行时由运行时链接文件加载库,这样可以节省系统的开销。

动态库一般后缀名为".so"。

gcc 在编译时默认使用动态库。完成了链接之后,gcc 就可以生成可执行文件,如下所示。

复制代码
gcc code.o --o code gcc

默认生成的二进制程序,是动态链接的,这点可以通过file 命令验证。


结语

这部分知识其实也并不多,了解.c文件变为可执行程序的过程即可,动态与静态库这里只作为提及,后续学习过程中我们会加深回他的理解,等今后的我们能力充足之后便可以熟知!

相关推荐
天狼122216 分钟前
第5章-1 优化服务器设置
运维·服务器·adb
傻啦嘿哟1 小时前
Python正则表达式:用“模式密码“解锁复杂字符串
linux·数据库·mysql
浪裡遊3 小时前
Linux常用指令
linux·运维·服务器·chrome·功能测试
SugarPPig3 小时前
PowerShell 查询及刷新环境变量
服务器
段ヤシ.4 小时前
银河麒麟(内核CentOS8)安装rbenv、ruby2.6.5和rails5.2.6
linux·centos·银河麒麟·rbenv·ruby2.6.5·rails 5.2.6
深夜情感老师6 小时前
centos离线安装ssh
linux·centos·ssh
我的作业错错错6 小时前
搭建私人网站
服务器·阿里云·私人网站
王景程6 小时前
如何测试短信接口
java·服务器·前端
微网兔子7 小时前
伺服器用什么语言开发呢?做什么用什么?
服务器·c++·后端·游戏
夸克App8 小时前
实现营销投放全流程自动化 超级汇川推出信息流智能投放产品“AI智投“
运维·人工智能·自动化