C语言进阶(9)

news2024/9/22 5:36:39

程序的执行时有两种环境,一种是翻译环境,另一种是执行环境。程序先经过编译成为obj的后缀的文件,然后将文件和链接库链接起来,然后将形成可执行程序,前者时翻译环境,后者时执行环境。(链接库就是库函数的所在和一些其他的)

1.翻译环境

翻译分为编译和链接,编译又分为预编译,编译和汇编;链接又分为合并段表和合并符号表和重定位。

预编译就是将一些引用的头文件转换和,#definde定义的进行替换,注释的删除等,就可以得到预编译的程序文件(后缀时.i)

编译就是将预编译的文件由C语言代码转变为汇编代码,编译器要进行语法分析,词法分析,符号汇总,语义分析的操作,得到后缀为.s的编译文件。其中语法分析就是将整个程序中函数,全局变量等进行汇总。

汇编就是将汇编代码转变成二进制指令和形成符号表,把汇编文件转变成以obj结尾的目标文件。这个符号表就是将每一个obj目标文件就是将符号汇总中进行匹配地址,就可以得到符号表。(如果没有函数体只是函数声明,就匹配一个无效地址)

链接的合并段表就是将不同文件(obj文件是linux elf文件的格式,内容是一段一段的)每一段进行合并。

链接的符号表的合并和重定位,就是将不同文件中的符号表进行合并,相同的符号,删除无效地址的符号,得到全新的符号表。重新根据符号的地址定位,最终得到可执行程序。

2.执行环境

执行环境的具体过程是

(1)将文件载入内存中;

(2)调用main函数

(3)执行程序代码和函数堆栈,存储函数的局部变量和返回地址;

(4)终止程序(有可能是意外终止和正常终止)

下面介绍预处理的详解

3.预处理符号

在编译器中自带一些符号,他们可以显示编译的一系列信息,相当于存储这些信息的变量:

__FILE__      //进行编译的源文件

__LINE__     //文件当前的行号,就是显示当前代码所在编译器的行号

__DATE__    //文件被编译的日期

__TIME__    //文件被编译的时间

__STDC__    //如果编译器遵循ANSI C,其值为1,否则未定义

下面是使用示例

\是续行符,可以将代码延申到下一行。 

4 .#define

(1)#define定义标识符

define可以定义常量,代码等,本质上是替换,将定义的替换成原来的,在进行汇编。

如下

(2)#define定义宏

宏就是一种类似函数形式,本质上是将宏参在文本中进行替换。然后将文本在主函数中进行替换后运算。

宏的声明方式是#define name( parament-list ) stuff,其中parament-list是宏参,是传给宏的参数,stuff是文本,然后就会进行文本宏参的替换和代码的替换。

下面是使用示例:

经过替换后可以写成

int main()
{
	printf("%d", ((2)+(3)));
	return 0;

}

经过完整的替换,文本是什么样就替换成什么样,这一点很重要!!!

我们为了防止出现出乎意料的结果,我们要每一个宏参加括号,整个文本加括号。

宏参可以出现其他#define定义的变量,但是不可以出现递归,字符串常量时不被检索。

宏和函数的对比:

函数

函数代码只出现于一个地方,每次使用这个函数时,都调用那个地方的同一份代码  存在函数的调用和返回的额外开销,所以相对慢一些

函数参数只在函数调用的时候求值一次,它的结果值传递给函 数。表达式的求值结果更容易预 测。

函数参数只在传参的时候求值一 次,结果更容易控制。

函数的参数是与类型有关的,如 果参数的类型不同,就需要不同的函数,即使他们执行的任务是 不同的。

函数是可以逐语句调试的

函数是可以递归的

#define定义宏

每次使用时,宏代码都会被插入到程序中。除了非常小的宏之外,程序的长度会大幅度增长 

宏参数的求值是在所有周围表达式的上下文环境里, 除非加上括号,否则邻近操作符的优先级可能会产生 不可预料的后果,所以建议宏在书写的时候多些括号。

参数可能被替换到宏体中的多个位置,所以带有副作用的参数求值可能会产生不可预料的结果。

参 数 类 型 宏的参数与类型无关,只要对参数的操作是合法的, 它就可以使用于任何参数类型。

宏是不方便调试的

 宏是不能递归的

(3)#和##

#是将非字符转变成字符

##是将两个符号合并成一个符号,这样的连接产生已申明的标识符,否则无效。

下面是使用示例

#和##只能在宏中使用。

(4)#undef

#undef就是将定义的宏进行删除,当我们需要重命名宏,发现重复时,就可以使用#undef来删除宏。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2039217.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【ComfyUI】Error occurred when executing WD14Tagger|pysssss :

解决ComfyUI的ComfyUI-WD14-Tagger插件运行报错问题 参考ONNX 运行时的 CUDA 和 cuDNN 加载错误 期刊 #56 pythongosssss/ComfyUI-WD14-标记器 (github.com) 我尝试了以下操作 转到 启动器, 启动CMD, 按回车键: 粘贴。卸载两个包 pip unin…

Linux之进程间通信(下)

目录 命名管道 命名管道的创建 匿名管道和命名管道的区别 命名管道的代码实现 共享内存 创建共享内存 关联共享内存 去关联共享内存 删除共享内存 共享内存特点 共享内存代码实现 IPC资源总结 命名管道 上期我们学习了匿名管道,匿名管道本质就是一个…

EcoVadis评估对可持续发展具体表现在哪些方面

Ecovadis认证是一项备受推崇的环保和社会责任认证,其优势不仅在于其权威性和公信力,更在于其全面而深入的评估标准,这个认证体系将企业划分为不同的等级,从入门级的银牌到最高级别的白金级,每个等级都有相应的评估标准…

Selenium + Python 自动化测试14(发送报告)

我们的目标是:按照这一套资料学习下来,大家可以独立完成自动化测试的任务。 上一篇我们讨论了使用HTMLTestRunner 生成HTML报告的方法。 本篇文章我们接着讲生成HTML报告是否可以自动邮件发送出去,提高我们测试报告的及时性,方便…

PCB入门笔记—绘制一个只有两个排针的PCB全流程记录—立创EDA专业版

PCB绘制入门🚀 硕士毕业之后准备进入博士阶段,本科阶段做的硬件,硕士阶段做的算法,然后博士阶段又要做回硬件了,因此也是打算补一补PCB相关的内容和知识,毕竟做控制的话,之后这也是不能躲开的必…

前端工程化-02.Yapi接口管理平台

YApi Pro-高效、易用、功能强大的可视化接口管理平台 图片中链接已失效,此处为新链接 选择添加接口,输入接口名称和接口路径。 创建成功后自动进入接口页面,点击编辑,可以编辑完善这个接口的信息。两个非常重要的信息&#xff1a…

进程waitwaitpid、线程

一、wait wait功能 1、获取子进程退出状态,分析子进程是否已经退出(变成僵尸态) 2、回收资源,让僵尸态子进程销毁 wait本身是一个阻塞操作,会使调用者阻塞 2、宏: (1)WIFEXITE…

bug的常见排查和分析思路以及相关的原因分类

作为开发人员,经常会收到来自用户和QA,领导反馈的各种问题。 为了快速问题,我们有时需要站在更高的角度,更全面的看待问题。才能更快锁定问题。 具体的bug还需要结合企业实际业务情况,相关的框架,依赖库&…

海康摄像头(测温型)桌面客户端开发分享

分享一个自己开发的用于企业特殊场景下温度监控告警的一个桌面应用。 关键功能: 1.支持海康摄像头; 2.支持多路视频预览,多通道画面选择预览,支持视频画面回放与下载; 3.支持自动探测摄像头功能,若具备…

RabbitMQ集群部署

RabbitMQ集群部署 简介 消息中间件RabbitMQ,一般以集群方式部署, 主要提供消息的接受和发送,实现各微服务之间的消息异步。 以下将介绍RabbitMQHA方式进行部署。 原理介绍 cookie ​ RabbitMQ底层是通过Erlang架构来实现的,所…

基于java五台山景点购票系统(源码+论文+部署讲解等)

博主介绍: ✌我是阿龙,一名专注于Java技术领域的程序员,全网拥有10W粉丝。作为CSDN特邀作者、博客专家、新星计划导师,我在计算机毕业设计开发方面积累了丰富的经验。同时,我也是掘金、华为云、阿里云、InfoQ等平台的优…

自建Gitlab和Gitlab runner并推送镜像到Harbor

1. 创建虚拟机 整体规划如下 1.1 创建3台虚拟机 系统版本Centos7.9 设置IP分别为 192.168.200.201 、192.168.200.202、 192.168.200.203 1.2 安装docker 3台虚拟机都安装docker,参考文章 安装docker 1.3 修改daemon.json 修改 /etc/docker/daemon.json 文件…

【数字信号处理】第3章 离散时间信号和系统的频域分析,系列的离散时间傅里叶变换,性质,定理(清华大学)

目录 第3章 离散时间信号和系统的 引言 信号和系统的分析方法有两种 模拟信号与系统的时域分析 模拟信号与系统的频域分析 离散时间信号和系统 历史回顾 3.1.1 序列的离散时间傅里叶变换 3.1.2 序列的离散时间傅里叶变换的性质 1. DTFT的周期性 2. 线性 3. 时移(位移…

守护网站心脏:HAProxy负载均衡技术详解(全网最详细)

守护网站心脏:HAProxy负载均衡技术详解 文章目录 **守护网站心脏:HAProxy负载均衡技术详解**haproxy介绍特点功能配置结论 haproxy负载均衡测试haproxy主机操作日志重定向操作 webserver1主机操作webserver2主机操作 haporxy相关配置测试backup参数测速h…

Petalinux 使用相关问题

文章目录 Petalinux 交叉编译环境Petalinux 以太网相关Petalinux 应用层写寄存器操作 Petalinux 交叉编译环境 方法一: 注意:该方法安装时会 和 Petalinux的 gcc-multilib 冲突; sudo apt install cmake sudo apt-get install gcc-arm-lin…

网络协议 十一 ARP,RARP,icmp,websocket,webservice,HTTPDNS,FTP,邮件相关的协议, SMTP,POP,IMAP

ARP 已知IP 求 MAC 的过程 RARP 已知MAC 求 IP 的过程,已被DHCP取代 ICMP websocket 协议,html5中提出的前端使用协议 webservice 技术,已过时 HTTPDNS 之前我们要获得 某一个域名的 IP ,要通过DNS协议 去 运营商的ISP 查询&…

Java | Leetcode Java题解之第327题区间和的个数

题目&#xff1a; 题解&#xff1a; class Solution {public int countRangeSum(int[] nums, int lower, int upper) {long s 0;long[] sum new long[nums.length 1];for (int i 0; i < nums.length; i) {s nums[i];sum[i 1] s;}return countRangeSumRecursive(sum,…

我对意义产生了怀疑!当今社会,一个最基本的因果律(深度好文)——早读(逆天打工人爬取热门微信文章解读)

有时候热搜也是一种预示 引言Python 代码第一篇 洞见 当今社会&#xff0c;一个最基本的因果律&#xff08;深度好文&#xff09;第二篇 空仓结尾 引言 今天真的晚 不过今天会更新两篇 破事真的多 有些人真的很神奇 在你做的时候不断来干预你 然后做得一般的时候就说 你的计划…

计算机图形学 | 动画模拟

动画模拟 布料模拟 质点弹簧系统&#xff1a; 红色部分很弱地阻挡对折 Steep connection FEM:有限元方法 粒子系统 粒子系统本质上就是在定义个体和群体的关系。 动画帧率 VR游戏要不晕需要达到90fps Forward Kinematics Inverse Kinematics 只告诉末端p点&#xff0c;中间…

Simple RPC - 03 借助Netty实现异步网络通信

文章目录 Pre设计技术点1. 接口设计2. 命令类设计3. 异步通信4. 异常处理与超时机制5. 背压机制6. 响应处理 Code封装通信 Transport 接口抽象数据的请求和响应 Command关于版本号 Transport 接口实现类 NettyTransport兜底的超时机制 背压机制 实现 总结 Pre Simple RPC - 01…