程序执行的环境和预处理

news2024/9/24 5:28:13
目录:
思维导图
一· 程序的翻译环境
二· 程序的执行环境
三· C 语言程序的编译和链接
四· 预定义符号
五· 预处理指令
六· 宏和函数对比
七· 预处理操作符# 和 ## 
八· 命令定义
九· 预处理指令#include
十· 预处理指令#undef
十一· 条件编译

WeChat_20240731222905

1· 程序的翻译环境

对于人机交换的计算机而言,他并不是一上来就能看懂我们直接写的代码的。这就好比一个只会说英语的外国人与一个只会说汉语的中国人进行交流一样,必须借助一个进行翻译的人员,才可以进行正常的交流。

对于计算机而言,是一样的道理。在我们编写的代码被执行之前需要经过2个不同的翻译环境

一个是翻译环境,一个是执行环境

翻译环境:把源代码转换成可执行的机器指令。

执行环境:进行代码的执行。

2· C 语言程序的编译和链接
2.1编译的环境

对于一个工程而言,可能不止一个源文件。每一个源文件都是单独经过编译器进行编译,生成对应的目标文件(后缀.obj)(注意:仅在Windows 环境下) 。

此时链接库经过链接器的处理和所有生成目标文件经过链接器处理,最终生成可执行程序(后缀.exe)

总的来说,一个程序的翻译环境大致分为2个过程:编译和链接

2.2 编译的多个阶段

其实对于源文件进行编译的这个过程还有许多的过程。

 过程1:预编译(预处理)

此过程主要是对文本进行操作。对所有的预处理指令(#include 包含的文件进行展开,#define 定义的符号进行替换)进行预处理,会生成对应的一个文件。

接下来主要是对预编译完之后文件的内容进行查看(注意:Linux系统)

打开服务器,使用Vim 这个编辑器进行一个文件(Test.c)的写入,文件名字大家随意,但是必须以.c为后缀,把此段程序写入后退出,敲下命令 gcc -E  test.c  -o Test.i

此指令的含义:预处理完之后就停下来,把生成的结果放到Test.i这个文件里面

这是对应Test.i 这个文件里面的内容:通过观察,对# include<stdio.h> 这个头文件所包含的内容进行了展开

过程2:编译

此过程的主要功能是进行语法的分析,符号的汇总,词法的分析,语义的分析把C语言代码翻译成汇编指令(注意此处的汇编指的是一种指令)

查看编译完之后对应文件内容,敲下指令:gcc -S Test.c -o Test.s

此时文件的内容都是一些汇编指令。 

过程3:汇编

此过程的功能是形成符号表同时生成目标文件后缀 .o (Linux系统下);把汇编指令翻译成二进制指令

对应的指令是: gcc -c Test.c -o Test.o

此语句含义:直接把Test.c 这个文件最终执行汇编完放到 Test.o 这个文件里面

最终的链接:

此时所有的链接库和所生成的目标文件经过链接这个过程生成对应的可执行程序。

链接过程 主要功能是:合成断表符号表的合成以及符号表的重定位(比如通过符号表找到调用

函数的地址)

2.3 运行环境
1. ) 程序必须载入内存中 。在有操作系统的环境中:一般这个由操作系统完成。在独立的环境中,
程序 的载入必须由手工安排,也可能是通过可执行代码置入只读内存来完成。
2. ) 程序的执行便开始。接着便 调用main函数
3. ) 开始执行程序代码。这个时候程序将使用一个 运行时堆栈(stack) ,存储函数的局部变量和
返回 地址。程序同时也可以使用静态(static)内存,存储于静态内存中的变量在程序的整个执行
过程 一直保留他们的值。
4. ) 终止程序 。正常终止 main 函数;也有可能是意外终止。
3· #define
3.1 预定义符号

 简单使用:

3.2 #define 定义宏

3.2.1 宏的定义

#define 机制包括了一个规定,允许把参数替换到文本中,这种实现通常称为宏( macro )或定义
宏( define macro )。
注意:
1)参数列表的左括号必须与宏的名字紧紧相邻
2)对宏体里面的内容尽可能的使用括号

3.2.2 宏的具体使用

1) 定义一个宏:求2个数的最大数

#include<stdio.h>
#define MAX(x,y) ((x)> (y) ? (x):(y))
int main()
{
	int a = 2, b = 5;
	int max = MAX(a, b);
	printf("%d\n", max);
	return 0;
}

2)定义一个宏:求一个数的平方

3)定义一个宏:求一个数的2倍

其实对于以上3个宏的实现 ,基本逻辑是一样的,只不过就是需要注意括号的使用

思考以下问题:

问题1:((x)+(x))  为什么最外一层还要加一层括号? 直接(x)+(x) 这样写不行吗 ?

 主要还是对于宏的使用,只会在预编译的阶段进行替换(可以说是一种“傻瓜式”的替换)

这就说明了一个问题一定不要吝啬括号的使用,对 (b)+(b) 最终加上括号  ((b)+(b))  就能很好解决问题了。

 问题2:直接(x+x)不就行了吗???

 通过查看预编译完之后的文件,可以知道编译器在对宏的替换,只是“傻瓜式”替换

 所以说:通过上面的错误用例,我们应该尽可能在不影响最终结果的前提下,使用()避免由于

操作符优先级引发的一系列副作用。

 3.2.3 #define 替换规则

1. 在调用宏时,首先对参数进行检查,看看是否包含任何由#define定义的符号。如果是,它们先

被替换。

2. 替换文本随后被插入到程序中原来文本的位置。对于宏,参数名被他们的值所替换。

3. 最后,再次对结果文件进行扫描,看看它是否包含任何由#define定义的符号。如果是,就重复

上述处理过程。

4· 宏和函数对比

以一个栗子进行论证吧:

写一个求最大数的函数和求一个最大数的宏

1)有无函数栈帧开销 

对于函数而言需要进行栈帧的开销:

 对于而言没有栈帧的开销

发现汇编指令里面并没有涉及到 call 相关的指令。

2) 带有副作用的参数

对于函数而言,参数只会在传参的时候进行一次的求值

对于宏而言,可能涉及到多个位置的替换,导致最终结果可能是无法预料的

康康以上程序的运行结果是啥。 

 

3)参数类型

对于函数而言,有参数类型的要求

对于宏而言,没有参数类型的检查

4)调试

函数支持调试;宏不能进行调试(预编译阶段已经被替换了)

5) 递归

函数支持递归;宏不支持递归

6)运行效率

宏更快,因为没有栈帧的开销;函数更慢

7)代码长度

宏的使用会导致程序代码冗余,只要是涉及到宏调用就会进行替换;对于函数而言,只出现一次,

每次调用函数的时候直接 call 调用函数地址就可以

8)操作符优先级

因为宏是“傻瓜式”替换,当涉及到操作符优先级问题的时候,可能出现误差;对于函数而言,在传

参的时候,会进行相关计算

9)命名约定

宏的名字一般全部大写;函数名字则不用(仅仅是使用习惯上的)

5· 预处理指令 #include
 5.1 #include 包含文件

在预处理阶段,会把所包含的文件内容进行展开(注意次展开是指内容的拷贝,不同于C++内联函数的展开)。

当同一个文件被多次包含的时候,也会被多次展开,可能会导致所生成的文件内容冗余

5.2 包含文件的2中方式

1)#include < >

这是一种库文件包含方式,用于对于库里面头文件的包含;编译器只会直接到库里面查找;若是没有直接报错

2)  #include" "

这是一种本地包含的方式;编译器会先在当前所在目录下进行查找;若是没有找到就会去库里面进

行查找,若不存在,最终报错。

可能有的老铁会有这样的问题:那对于库文件的包含是不是也可以用“”  

但是这样会降低效率

6· 预处理操作符 #  和  ## 

 先看看以下代码:

 

 通过运行结果,我们可以得知:字符串可以进行自动拼接

 是否可以借助宏进行字符串的拼接呢

6.1 #

# :这个符号作用就是把宏参数变成对应的字符串

注意:要求当字符串作为宏参数放到一个字符串里面

 使用:

 6.2 ##

## 作用:把位于他两边的符号合成一个符号

使用:

7· 命令行定义
7.1定义
许多 C 的编译器提供了一种能力,允许在命令行中定义符号用于启动编译过程
例如:当我们根据同一个源文件要编译出一个程序的不同版本的时候,这个特性有点用处。
(假定某个 程序中声明了一个某个长度的数组,如果机器内存有限,我们需要一个很小的数组,
但是另外一个机器 内存大些,我们需要一个数组能够大些。)
换言之就是,对于跨平台的程序而言,可以在编译的过程中使用
以Linux 系统为例:数组大小暂定
编译以下程序:
7.2使用

在编译的时候指定数组 SZ大小 SZ= 10

指令: gcc test.c -D SZ=10 test

此时数组内容:

8· 预处理指令#include
8.1 #include

在预编译的阶段,# include 所包含的文件都会被进行展开(文件内容会被进行拷贝)

8.2 其他预处理指令

9· 指令#undef
作用:

用于移除一个宏定义

10· 条件编译
1)#if  ……  #endif

 使用:

2)多分支条件编译

使用:

 

3)判断一个符号是否被定义过 

 

使用:

4)判断一个符号是否没有定义

 使用:

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

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

相关文章

JavaScript 打印 V 和倒 V 图案的程序(Program to print V and inverted-V pattern)

倒 V 型模式&#xff1a;给定 n 的值&#xff0c;打印倒 V 型模式。示例&#xff1a; 输入&#xff1a;n 5 输出 &#xff1a; E D D C C B B A A 输入&#xff1a;n 7 输出 &#xff1a; G F F E E D D C C B B A…

中药养发护发

按照中医理论,头发和肝肾有密切联系,肝主血,肾藏精, 其华在发,肝肾强健,上荣于头,则毛发乌黑浓密. 中药育发的应用 以当归,天麻,桑疹子养血润发,配合干姜祛风活血,能通畅经络, 加快循环,激活毛囊,能促进皮肤组织营养成分吸收和废弃物的排泄,改善 头发生态. 用苦参 皂角 清热化…

yum仓库的制作与使用

目录 前言&#xff1a; 1 查看系统内核 2 获取网络源 3 搭建yum网络仓库 4 rpm包的下载 4.1 将rpm包下载至本地 4.2 对下载的rpm包进行备份 5 制作本地yum源 5.1 软件仓库制作工具createrepo 5.2 使用createrepo创建本地yum仓库 6 搭建docker本地仓库 前言&#x…

【Dash】使用 HTML 和 CSS 创建图表

一、Styling Your App The examples in the previous section used Dash HTML Components to build a simple app layout, but you can style your app to look more professional. This section will give a brief overview of the multiple tools that you can use to enhan…

Scalable Diffusion Models with Transformers(DIT)代码笔记

完整代码来源&#xff1a;DiT DiT模型主要是在diffusion中&#xff0c;使用transformer模型替换了UNet模型&#xff0c;使用class来控制图像生成。 根据论文&#xff0c;模型越大&#xff0c;patch size 越小&#xff0c;FID越小。 模型越大&#xff0c;参数越多&#xff0c;pa…

3.罗马数字转数字

3.罗马数字转数字 题目题目分析 题目 题目分析 基础思路是先想到键值对&#xff0c;然后遍历字符串利用键值对匹配来计算值&#xff0c;要注意处理IV&#xff0c;IX之类需要将当前处理字符与前一个字符进行比较。 class Solution { public:int romanToInt(string s) {//这个函…

项目负责人视角:结构化思考在竞赛中的力量

项目负责人视角&#xff1a;结构化思考在竞赛中的力量 前言结构化思考的定义与重要性结构化思考的五个关键步骤1. 明确问题2. 问题分解3. 优先级排序4. 制定行动计划5. 执行与监控 结构化思考的实际应用案例结语 前言 在这个充满挑战和机遇的时代&#xff0c;项目管理已成为企业…

Nero Lens 智图 - 适用于 iOS 和 iPadOS 的专业图片处理 App

首先是手机端的无损放大 App&#xff1a;Nero Lens 智图&#xff0c;适用于 iOS 和 iPadOS&#xff0c;不仅可以放大&#xff0c;还有多种 AI 图片增强功能。 使用这款 App 可以通过 AI 模型智能放大可达 400%&#xff0c;还有老照片去划痕、上色&#xff0c;抠图移除背景、照…

数论第四节:不定方程(习题)

文章目录 例1例2例3例4例5 例1 解下列不定方程&#xff1a; ( a ) 15 x 25 y 100 (a)15x25y100 (a)15x25y100 ( b ) 306 x − 360 y 630 (b)306x-360y630 (b)306x−360y630 (a)解: (15,25)5&#xff0c;且5|100&#xff0c;所以方程有解。 方程两边同时除以(15,24)&…

53 SSLVPN IP 接入

(1) 配置接口IP地址 # 根据组网图中规划的信息,配置各接口的IP地址,具体配置步骤如下。 <Device> system-view [Device] interface gigabitethernet 1/2/5/1 [Device-GigabitEthernet1/2/5/1] ip address 1.1.1.2 255.255.255.0 [Device-GigabitEthernet1/2/…

Unity获取Animator动画播放完成事件

整理了一些在日常经验中处理动画播放完成事件的方法 方法: 1.Dotween配合异步实现 2.状态机计时方法实现 3.原生动画行为方法实现 方法一&#xff1a;Dotween异步方法 using UnityEngine; using System.Threading.Tasks; using DG.Tweening;public class PlayerAnimAsync : M…

从Excel高手到SQL大师-解锁数据分析的无限潜力 -10分钟读懂职场必备技能

目录 Excel 和 SQL&#xff1a;看似相似却大不相同的数据处理利器Excel vs SQL&#xff1a;表面相似&#xff0c;本质迥异Excel&#xff1a;直观但受限的电子表格SQL&#xff1a;强大而灵活的数据库查询语言 从 Excel 到 SQL&#xff1a;跨越鸿沟Excel 数据筛选SQL 数据筛选 结…

MySQL:数据库权限与角色

权限 MySQL 的权限管理系统是保障数据库安全性的关键组件之一。它允许数据库管理员精确控制哪些用户可以对哪些数据库对象执行哪些操作。 自主存取控制 DAC&#xff08;DiscretionaryAccess Control)&#xff1a;用户对于不同的数据库对象有不同的存取权限&#xff0c;不同的…

Java并发编程中的FutureTask详解

Java并发编程中的FutureTask详解 1、核心特点2、基本用法2.1 包装 Callable 任务2.2 包装 Runnable 任务 3、注意事项 &#x1f496;The Begin&#x1f496;点点关注&#xff0c;收藏不迷路&#x1f496; FutureTask 是 Java 并发包 java.util.concurrent 中的一个类&#xff0…

Trimble 电子水准仪数据传输与预处理

0 安装软件。 1 将设备传输线与电脑相连接。 2 运行软件&#xff0c;选择对应的设备&#xff0c;显示连接成功。 3 点击添加&#xff0c;选择工程文件&#xff0c;再点击打开&#xff08;可以选择多个&#xff09;。 4 点击Transfer All&#xff0c;数据会传输到对应路径。 5 查…

职场生存秘籍:16条黄金法则

作者简介&#xff1a;一名计算机萌新、前来进行学习VUE,让我们一起进步吧。 座右铭&#xff1a;低头赶路&#xff0c;敬事如仪 个人主页&#xff1a;我叫于豆豆吖的主页 写在前面 在这个瞬息万变的时代&#xff0c;职场不仅是实现个人价值与梦想的舞台&#xff0c;更是一…

操作列表(运用for循环)

1、遍历整个列表 1.1、使用for循环 对列表中的每个元素都执行相同的操作&#xff0c;这就需要使用到for循环。 例&#xff1a;运用fou循环&#xff0c;把列表中的元素依次打印出来 citys[beijing,jiangxi,chongqing] for city in citys:print(city) 输出很简单&#xff0c;…

Spring Boot 整合 Dubbo3 + Nacos 2.4.0【进阶】+ 踩坑记录

上一篇文章中&#xff0c;Spring Boot 整合 Dubbo3 Nacos 2.4.0 进行了简单的集成使用&#xff0c;此文简单进阶并记录踩坑日常&#xff1b; Nacos 2.4.0 增加鉴权的配置Nacos 2.4.0 配置 MySQLNacos2.4.0 的热更新Dubbo3 自动负载Dubbo3 的重试和超时机制踩坑记录 一、Nacos…

Spring - 统一返回数据格式

T04BF &#x1f44b;专栏: 算法|JAVA|MySQL|C语言 &#x1faf5; 今天你敲代码了吗 文章目录 1. 使用2. 字符串问题2.1 解决方法:2.2 问题分析 有时候后端返回的响应可能是String,Boolean之类的类型,但是我们希望响应将可能描述清除,如失败的原因等由于一次只能返回一个对象,因…

SpringBoot配置文件高级用法实战

❃博主首页 &#xff1a; 「码到三十五」 &#xff0c;同名公众号 :「码到三十五」&#xff0c;wx号 : 「liwu0213」 ☠博主专栏 &#xff1a; <mysql高手> <elasticsearch高手> <源码解读> <java核心> <面试攻关> ♝博主的话 &#xff1a…