C语言进阶(9)

程序的执行时有两种环境,一种是翻译环境,另一种是执行环境。程序先经过编译成为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.rhkb.cn/news/400533.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C语言——构造类型

构造类型 数据类型分类 结构体 结构体的定义 定义:自定义数据类型的一种,关键字 struct ,结构体类型的变量可以存储多个不同数据类型的数据。 定义格式: struct 结构体名 { 数据类型1 成员名称1; 数据类型2 成员名称2; … } 注…

element-plus的表单输入框有清除按钮的,文字输入前后宽度不一致怎么解决

输入内容之后多了一个可清除的图标,输入框的宽度也被撑开了 根据输入前后的dom对比发现,多了一个图标的span标签 :deep(.el-input__wrapper) {position: relative;.el-input__inner {padding-right: 18px;}.el-input__suffix {position: absolute;right:…

【qmake: No such file or directory 的问题解决最全】

尝试1 qmake: could not exec ‘/usr/lib/x86_64-linux-gnu/qt4/bin/qmake’: No such file or directory 执行 qmake -v出现错误:qmake: could not exec ‘/usr/lib/x86_64-linux-gnu/qt4/bin/qmake’: No such file or directory 分析: qtchooser默…

【简历】北京某985大学:JAVA秋招简历指导,面试通过率较高

注:为保证用户信息安全,姓名和学校等信息已经进行同层次变更,内容部分细节也进行了部分隐藏 简历说明 我们今天要看一位来自25届985同学的JAVA简历。 既然要参加校招的话,我们校招法典的第一准则:定你的学校层次。 …

Java面试八股之什么是消息队列

什么是消息队列 消息队列(Message Queue)是一种应用程序间通信(IPC)的形式,它允许进程将消息发送到另一个消息队列,接收端则可以在任何时刻从队列中取出这些消息进行处理。消息队列提供了一种异步处理、解…

java后端正式的企业级项目规范——苍穹外卖篇一

我在极速一个月学完黑马的《java web》课程之后跟着他写了一个java后端项目,但是后面我才发现那只是为了巩固基础的一个简单课程项目,跟实际开发的项目根本不一样。然后后面我暑假去了超星的移动图书馆开发部实习(我主要做前端的)…

深度优化Nginx负载均衡策略,携手Keepalived打造高可用服务架构新纪元

作者简介:我是团团儿,是一名专注于云计算领域的专业创作者,感谢大家的关注 座右铭: 云端筑梦,数据为翼,探索无限可能,引领云计算新纪元 个人主页:团儿.-CSDN博客 目录 前言&#…

【JavaEE初阶】文件操作和IO

目录 🌴认识文件 🚩树型结构组织和目录 🚩文件路径(Path) 🚩 文件分类 🎍Java 中操作文件 🚩 File 概述: 📌属性 📌构造方法 &#x1f4c…

企业大模型业务架构技术选型分析

AI赋能企业:选择适合你的大模型业务架构 现代企业中,大模型业务日益普及,主要涵盖AI Embedded、AI Copilot和AI Agent三大架构。本文深入剖析其特性与适用场景,为企业选择合适的大模型业务架构提供指导,助力企业高效应…

Spring容器启动的过程(main)

大体流程如下 1、初始化 首先,Spring会通过用户提供的配置信息(例如XML文件或者注解)来初始化一个BeanFactory,这个BeanFactory是Spring容器的核心,它负责创建和管理所有的Bean。 2、读取配置生成并注册BeanDefini…

开源一套金融大模型插件(ChatGPT)

shares vscode 插件A 股量化交易系统自研金融大模型,复利Chat 源码地址: https://github.com/xxjwxc/shares

面试题:Rabbitmq怎么保证消息的可靠性?

1.消费端消息可靠性保证: 消息确认(Acknowledgements):(自动(默认),手动) 消费者在接收到消息后,默认情况下RabbitMQ会自动确认消息(autoAcktrue)。为保证消息可靠性,可以设置auto…

CentOS 7设置静态IP地址的详细指南

CentOS 7设置静态IP地址的详细指南 配置静态IP地址是服务器或虚拟机管理的重要步骤之一,特别是在需要稳定、可预测的网络环境时。本文将详细介绍如何在CentOS 7上设置静态IP地址,帮助确保你的系统网络配置符合需求。 1. 查看当前网络配置 在进行任何更…

文件长度超出芯片容量, 超出部份将被忽略!ch341a编程器报错解决方法

出现这个错误提示,说明你正在刷的是华硕主板的cap格式BIOS文件。 编程器不支持这种文件,需要转换成编程器专用版本BIOS文件。 华硕cap格式BIOS转编程器bios文件,转换工具下载地址:https://download.csdn.net/download/baiseled/88…

再见Figma!!新的设计,代码协作神器!【送源码】

软件介绍 Penpot 是一款专门用来帮助设计师和开发者更好地合作的软件。它可以让设计师轻松地做出漂亮的设计稿,还能让这些设计稿变成真正的网站或者应用的一部分。这样,设计师和开发者之间就不会因为沟通不畅而产生麻烦了。 Penpot 专为设计师与开发者之…

在docker中进行日志切割

先在Linux中安装docker,然后在docker中安装appnode面板,并进行docker网络端口映射。接着进入docker,进行nginx日志切割。 安装docker 第一步,卸载旧版本docker。 若系统中已安装旧版本docker,则需要卸载旧版本docke…

书生大模型实战营-基础关-XTuner 微调个人小助手认知

XTuner 微调个人小助手认知 环境配置模型效果预览微调数据准备微调配置微调训练权重格式转换模型合并页面对话 环境配置 # 创建虚拟环境 conda create -n xtuner0812 python3.10 -y# 激活虚拟环境(注意:后续的所有操作都需要在这个虚拟环境中进行&#…

Docker搭建Minio容器

Docker搭建Minio容器 前言 在上一集我们介绍了分布式文件存储行业解决方案以及技术选型。最终我们决定选用Minio作为分布式文件存储。 那么这集我们就在Docker上搭建Minio容器即可。 Docker搭建Minio容器步骤 创建Minio文件目录 我们选择创建/minio/data目录 修改目录权…

40.x86游戏实战-找出XXX遍历周围的类型

免责声明:内容仅供学习参考,请合法利用知识,禁止进行违法犯罪活动! 本次游戏没法给 内容参考于:微尘网络安全 工具下载: 链接:https://pan.baidu.com/s/1rEEJnt85npn7N38Ai0_F2Q?pwd6tw3 提…

【C#】中IndexOf的用法

在 C# 中&#xff0c;IndexOf 方法是字符串和列表&#xff08;如 List<T>&#xff09;等数据结构中常用的方法&#xff0c;用于查找指定元素或子串首次出现的位置。以下是针对不同情况使用 IndexOf 的示例。 对于字符串 对于字符串类型&#xff0c;IndexOf 方法返回子字…