c语言编译过程,满满的干货!!!(代码片段)

SuchABigBug SuchABigBug     2022-12-15     639

关键词:

一、程序翻译和运行环境

翻译环境:在翻译环境中,我们写的源代码转换为可执行的机器指令,让机器能够看的懂,模块包括预处理,汇编,编译和链接最终生成的可执行程序.exe或者 a.out

  1. 每个源文件通过编译分别转换成目标代码(.o文件)
  2. 每个目标文件由一个链接器(linker)捆绑在一起,形成一个可执行程序
  3. Linker同时也会引入标准C函数任何被该程序所引用的函数,包括个人的程序库,将其需要的函数也链接到程序中

预处理阶段:

#include <stdio.h>
#define globalVal 88

int main()
	
	//	这个是注释comment
    int num = globalVal;
    printf("%d \\n", num);
    
    return 0;


我们到预编译阶段停止,把预编译后的结果写到test文件中

我们可以看到#include <stdio.h>被替换为源代码,变量globalVal被替换成了数字88,同时注释也被删除

编译阶段:

把C语言代码转化成汇编代码

  1. 语法分析
  2. 词法分析
  3. 语义分析
  4. 符号汇总

用-S进行转换并写入test文件中

下图为生成的test.s文件中的内容

汇编阶段
编译器中的最后一个阶段,把汇编代码转换成了机器指令(二进制)

  1. 生成符号表
  2. 生成.o文件是elf格式,我们可以用readelf来查看这个table


链接器阶段
翻译环境中的最后一个阶段,把生成的多个目标文件(.o文件)和库进行连接,合并段表和符号表的合并和符号表的重定位,如_main函数和其他的主函数可以通过ref table的地址进行链接


翻译环境总结:
预编译主要是进行的文本操作,如完成头文件的包含,#define的定义符号和宏的替换,最后注释删除。
接着就是编译阶段(把C语言转换成汇编代码),而汇编是把汇编指令转换成二进制指令最后生成我们的目标文件
然后多个源文件经过编译器处理生成的多个目标文件最后会经过链接器的处理生成我们的可执行程序

运行环境:用于实际执行代码

二、预处理详解

1. 预定义符号

__FILE__      //进行编译的源文件
__LINE__     //文件当前的行号
__DATE__    //文件被编译的日期
__TIME__    //文件被编译的时间
__STDC__    //如果编译器遵循ANSI C,其值为1,否则未定义

2. define 定义宏

#define int 888

这里建议后面不要加上semi colon,否则替换之后会报错

还有一个需要注意的是加上括号()以此避免优先级错误
比如:

#define SQUARE(X) X * X
int main()
	if(SQUARE(3 + 1) != 16)
		printf("something goes wrong ! \\n");
	
	return 0;

我们预期这个结果是16,-E预编译后写入一个文件,这个被转换成了(3+1*3+1),那这个结果算出来肯定就不对了呀,所以正确的办法是在宏定义SQUARE的时候加上括号才能达到预期((X) * (X))。

3. #和##的区别

#就是把输入函数的参数转换成字符串,可以和宏一起用,如调用宏SQUARE(NUMISThree),可以这个变量名转换成字符串形式打印出来

如下图就是通过了#进行连接的:


##
此符号可以把位于它两边的符号合成一个符号,就相当于 linux下的cat操作

4. 宏和函数好坏比较

函数
代码长度每次使用时,预处理阶段都会进行替换,一般stdio.h替换万后有五百多行函数只出现一个地方,每次使用也都调用那个地方也就是我们说的符号表中函数的地址
执行速度宏更快,可以看预处理阶段就直接替换就好存在函数调用和返回的额外开销,相对慢
操作法优先级容易搞混淆,就如我们上面的例子SQAURE(X),不加括号容易产生优先级错误表达式的求值结果更容易预测
带有副作用的参数宏与类型无关,只要对参数操作是合法的即可,不够严谨但是函数就和类型息息相关,如果类型不同就会报错
调试宏不方便调试,因为预处理阶段已经完成了转换可以逐个调试
递归宏不能递归函数可以进行递归

而在C++中,有个函数叫内联(inline),即继承了宏的优点,也兼顾了函数的优点

5. 命名约定

可以在编译指令中进行变量声明
MAX_SIZE= 10
然后在程序中直接使用此变量名即可

6. 头文件中 < >和" "区别

本地文件包含,自定义的函数头文件使用 “ ”
库文件包含 < >

<> 和 “ ”包含头文件的本质是查找策略的区别, 双引号的查找策略是先在源文件所在目录下查找
如果该头文件未找到,编译器就像查找库函数头文件一样在标准位置查找头文件

7. 条件编译

条件编译的用处是防止文件中多次包含同一个库文件,那么在预处理阶段就多出现大量的冗余,因此我们可以用条件编译来判断此文件是否被重复用过,或者判断是运行macos文件,还是WIndows还是Linux。

第二种办法更简单就是在文件开头用#pragama once也能达到一样的效果

1. 
	#define __SHOWLINE__
2. 
	#ifdef __SHOWLINE__
	XXX
	XXX
	#endif
3. 
	#if 0	// 敞亮表达式,用于mute内容,可供后期调试
		XXX
		XXX	
	#endif
4.
	#if	//多个分支的条件编译
	#elif
	#else
	#endif
5.
	#if defined(XXX) 
	等价于
	#ifdef XXX
	
	#if !defined(XXX)
	等价于
	#ifndef XXX	

如果文章对你有帮助的话,给作者点个赞加个油,俺会更有动力的!😃

mysql最全笔记,快速入门,干货满满,爆肝(代码片段)

目录一、MySQL的重要性二、MySQL介绍三、软件的服务架构四、MySQL的安装五、SQL语句六、数据库相关(DDL)七、表相关八、DML相关(表中数据)九、DQL(重点)十、数据完整性十一、表与表之间的关系一、MyS... 查看详情

javascript的核心语法之变量(绝对详细,干货满满)(代码片段)

JavaScript与其它程序设计一样,也都有着自己独特的语法结构,,主要包含变量、数据类型、运算符号、控制语句和注释等等。变量(三种使用方式) 说明:变量是由于存储数据的基本单位  方式1:... 查看详情

动态开辟内存的这些知识你知道了吗?了解柔性数组吗?超详细画图以及文字讲解,干货满满(代码片段)

...元素存储内存中在连续的位置上,它所需要的内存在编译时就被分配,但是我们也可以使用动态内存分配在运行时为它分配内存,下面博主将以以下内容介绍动态 查看详情

javascript核心语法之基本数据类型(绝对详细,满满干货)(代码片段)

数据类型    1.JavaScript中有五种简单的数据类型,被称为基本数据类型,分别是:undefined---未初始化的变量以及未声明的变量null---空类型boolean---true或falsenumber---整数或浮点数string---用双引号来进行声明的字符串  ... 查看详情

oa多级审批流程表设计方案(干货满满)(代码片段)

...核心业务,审批流程是如何一步步实现的。本文干货满满,建议静下心来细细品被审核流程首先填写好表单相关信息,然后点击审批人,从公司部门树中点击相应 查看详情

oa多级审批流程表设计方案(干货满满)(代码片段)

...核心业务,审批流程是如何一步步实现的。本文干货满满,建议静下心来细细品被审核流程首先填写好表单相关信息,然后点击审批人,从公司部门树中点击相应 查看详情

梦开始的地方——c语言预处理+编译过程(代码片段)

文章目录C语言程序的编译(预处理)1.编译和链接1)编译的几个阶段预编译阶段编译阶段汇编阶段2)链接2.预处理1)预定义符号2)#define3)#和##4)带副作用的宏参数5)宏和函数对比3.常见预处理命令1)#undef2)命令行定义3)条件编译4)文件包含5... 查看详情

一位博士在华为的22年(干货满满)(代码片段)

星标/置顶 公众号👇,硬核文章第一时间送达!来源| 心声社区作者| Clayman前几天,我的一个朋友外派迪拜三年多,历经千辛万苦回来深圳,聊了很多有些感慨,分享一篇相关文章。转眼在我厂已经... 查看详情

一位博士在华为的22年(干货满满)(代码片段)

星标/置顶 公众号👇,硬核文章第一时间送达!来源| 心声社区作者| Clayman前几天,我的一个朋友外派迪拜三年多,历经千辛万苦回来深圳,聊了很多有些感慨,分享一篇相关文章。转眼在我厂已经... 查看详情

java认识顺序表及常用操作函数(干货满满!!)(代码片段)

目录一、线性表二、什么是顺序表?实现顺序表:三、顺序表的常用操作实现:(1)在pos位置新增元素(2)打印顺序表(4)判定是否包含某个元素(4)查找某个元素对应的位置(5)获取pos位置的元素(5)获取... 查看详情

杭州黑马java培训多少钱,干货满满(代码片段)

01.第一份资料是图解网络根据读者阅读偏好不同,共出了两个版本风格的PDF,分别是亮白版本和暗黑版本。02.第二份资料是计算机的相关知识看完能让你对计算机有一个基础的了解和入门,是培养你 内核 的基础ÿ... 查看详情

c语言编译过程(代码片段)

C语言编译过程#mermaid-svg-5rPU3g0o30PkwiNU.labelfont-family:\'trebuchetms\',verdana,arial;font-family:var(--mermaid-font-family);fill:#333;color:#333#mermaid-svg-5rPU3g0o30PkwiNU.labeltextfill:#333#merm 查看详情

基于springcloud的微服务架构脚手架,满满的干货来啦~(代码片段)

文章目录1前言2脚手架主要提供哪些功能3如何使用该脚手架3.1项目统一依赖管理3.2集成基础模块功能到自己的项目中4基础核心功能模块的使用4.1集成缓存管理模块4.1.1添加cache模块依赖4.1.2cache模块的功能使用4.2集成通知预警管理... 查看详情

基于springcloud的微服务架构脚手架,满满的干货来啦~(代码片段)

文章目录1前言2脚手架主要提供哪些功能3如何使用该脚手架3.1项目统一依赖管理3.2集成基础模块功能到自己的项目中4基础核心功能模块的使用4.1集成缓存管理模块4.1.1添加cache模块依赖4.1.2cache模块的功能使用4.2集成通知预警管理... 查看详情

c语言游戏超详解扫雷游戏完整版,细节满满!!(代码片段)

目录 扫雷扫雷游戏规则介绍如何将扫雷游戏实现代码基本思路分步代码实现创建和打印游戏菜单初始化棋盘打印棋盘布置雷排查雷游戏主体——game()函数总代码实现game.htest.cgame.c总结扫雷实现扫雷的算法有很多种ÿ... 查看详情

oa多级审批流程表设计方案(干货满满)(代码片段)

点击上方关注“终端研发部”设为“星标”,和你一起掌握更多数据库知识来源:blog.csdn.net/cslx5zx5/article/details/107566070上一篇:面试官:int(1)和int(10)有什么区别?大家好,我是终端研发部的小于哥。OA(offic... 查看详情

那些神题和它的改编消失的数字iiiiiiiv(全系列,干货满满)(代码片段)

消失的数字PartI、消失的数字IPartII、消失的数字II方法一:求差方法二:异或法PartIII、消失的数字IIIPartIV、消失的数字IVPartV、检验自己PartI、消失的数字I给定一个非空整数数组,除了某个元素只出现一次以外,其... 查看详情

c语言面试干货——c语言自增/自减操作的陷阱(代码片段)

文章目录C语言面试干货——C语言自增/自减操作的陷阱【陷阱1】自增/自减在==表达式求值==中的陷阱【陷阱2】在==printf==中使用自增/自减的陷阱【避免】**上面的问题怎么避免?**自增/自减面试==... 查看详情