程序环境和预处理

devtools/2024/10/7 21:32:25/

翻译环境,在这个环境中源代码被转换为可执行的机器指令

执行环境,它用于实际执行代码

翻译环境

翻译环境分为编译与链接,是将我们编译的代码转换成程序运行的二进制代码进行转换。下面是讲述翻译环境: 

  • 组成一个程序的每个源文件通过编译过程分别转换成目标代码(.obj)。
  • 每个目标文件由链接器捆绑在一起,形成一个单一而完整的可执行程序(.exe)。
  • 【链接器同时也会引入标准C函数库中任何被该程序所用到的函数,而且它可以搜索程序员个人 的程序库】链接库,将其需要的函数也链接到程序中。

编译 

编译分为预编译(预处理)、编译、汇编,下面讲这些程序的作用:

         预编译(预处理)

预编译是将头文件包含、宏定义的替换和删除、 注释删除等文本操作,是将.c文件进行预处理后变成.i文件。

          编译

 将C语言代码经过语法分析、词法分析、语义分析、符号汇总翻译成汇编代码,生成.s文件。

          汇编

将汇编代码翻译成二进制代码,在VS下生成的是.obj文件,在vscode-gcc环境下生成的是.o文件(目标文件)。

链接

所有的文件合并成一个可执行文件(.exe)。

运行环境

1. 程序必须载入内存中。在有操作系统的环境中:一般这个由操作系统完成。在独立的环境中,程序 的载入必须由手工安排,也可能是通过可执行代码置入只读内存来完成。

2. 程序的执行便开始。接着便调用main函数。

3. 开始执行程序代码。这个时候程序将使用一个运行时堆栈(stack),存储函数的局部变量和返回 地址。程序同时也可以使用静态(static)内存,存储于静态内存中的变量在程序的整个执行过程 一直保留他们的值。

4. 终止程序。正常终止main函数;也有可能是意外终止。

------------预处理 

1.预定义符号

 2.#define

                2.1#define定义标识符       (所有的定义都不需要加;)

#define MAX 1000【将函数中的MAX替换成1000】

#define reg register  【为 register这个关键字,创建一个简短的名字】      

#define do_forever for(;;)    【将do_forever替换成for(;;)死循环】

#define CASE break;case  【将CASE替换成break;case,所以第一个case还是小写】

                 2.2#define定义宏

#define SQUARE( x ) x * x  【SQUARE( 5 ); -->  5*5;】

                                            【int a = 5; printf("%d\n" ,SQUARE( a + 1) );--> a+1*a+1;】

 所以定义宏时不要吝啬括号

                  2.3#define替换规则

                  2.4#和##         (只能在宏中定义)

int i = 10;

#define PRINT(FORMAT, VALUE) printf("the value of " #VALUE "is "FORMAT "\n", VALUE)

【PRINT("%d", i+3);-->  the value of i+3 is 13\n

代码中的 #VALUE 会预处理器处理为:"VALUE"

 #define SUM(x, y) x##y

【 SUM(L, X) = 100;-->   printf("%d\n", SUM(L, X));】  

                 2.5带副作用的宏参数

z = (x++)  >  (y++)  ?  (x++)  :  (y++); //首先需要判断两个数的大小所以需要先使用值再++,得到x=6,y=9.然后就是执行后面的语句为假y++ ,同样也是先使用值,所以z=9,原本y的值是9,再++则y=10,x不变x=6。

宏和函数对比

  • 宏比函数在程序的规模和速度方面更胜一筹;
  • 函数需要定义类型,宏不需要;
  • 使用宏会让原本长的代码加长;
  • 函数可以,宏不能调试;
  • 宏可能带来运算符优先级的问题,所以要括号;
  • 参数可能被替换到宏体中的多个位置,所以带有副作用的参数求值可能会产生不一样的结果;
  • 宏不能递归,函数可以;

                  2.6命名约定:一般宏全大写,函数首字母大写或驼峰表示法; 

 3.#undef

 4.命令行定义

某个程序中声明了一个某个长度的数组,如果机器内存有限,我们需要一个很小的数组,但是另外一个机器内存大,我们需要一个数组能够大一些。

5.条件编译

          常见的条件编译指令

(1.

(2.多分支条件编译

 

(3. 是否被定义

(4.嵌套指令 

 5.文件包含

库文件是放在标准库里面的, 虽然库文件也可以使用“”进行包含, 但是这样效率就会变低,而且这样不容易区分本地文件和库文件了。

  •  #pragma once       //当一个项目中文件数过多, 可能出现头文件重复包含的情况。
  • 或者在头文件中这样写,也是只包含一次。


http://www.ppmy.cn/devtools/122596.html

相关文章

计算机网络:计算机网络体系结构 —— 专用术语总结

文章目录 专用术语实体协议服务服务访问点 SAP 服务原语 SP 协议数据单元 PDU服务数据单元 SDU 专用术语 实体 实体是指任何可以发送或接收信息的硬件或软件进程 对等实体是指通信双方处于相同层次中的实体,如通信双方应用层的浏览器进程和 Web 服务器进程。 协…

通信工程学习:什么是LAN局域网、MAN城域网、WAN广域网

LAN局域网、MAN城域网、WAN广域网 LAN(Local Area Network,局域网)、MAN(Metropolitan Area Network,城域网)和WAN(Wide Area Network,广域网)是计算机网络中根据覆盖范围…

前端DOM常用操作

前端DOM常用操作及代码案例 在前端开发中,DOM(文档对象模型)操作是不可或缺的一部分。通过DOM,开发者可以查找节点、增删节点、修改节点内容、操作CSS样式等。本文将介绍一些常用的DOM操作,并提供相应的代码案例。 一…

【C++】--类和对象(2)

👌个人主页: 起名字真南 👆个人专栏:【数据结构初阶】 【C语言】 【C】 目录 1 类的默认成员函数2 构造函数3 析构函数4 拷贝构造5 赋值运算符重载5.1 运算符重载5.2 赋值运算符的重载 1 类的默认成员函数 默认成员函数就是用户没有显示实现,…

rabbitMq------客户端模块

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言消费者模块信道管理模块管理的字段提供的接口 信道内存管理连接管理类 前言 在RabbitMQ中,提供服务的是信道,因此在客⼾端的实现中&…

力扣 中等 216组合总和III

文章目录 题目介绍解法 题目介绍 解法 是77.组合链接的扩展 class Solution {List<List<Integer>> result new ArrayList<>();List<Integer> path new ArrayList<>();public List<List<Integer>> combinationSum3(int n, int k) …

docker常见命令

1.镜像操作 镜像名称分成两个部分&#xff1a;[repository]:[tag] repository指的是镜像名称tag指的是镜像的版本 比如&#xff1a;mysql:5.7 其中mysql就是repository&#xff0c;而5.7指的就是tag 注意&#xff1a;以后在输入镜像名称的时候&#xff0c;都需要按照这个模式来…

VMware ESXi 6.7U3u macOS Unlocker 集成驱动版更新 OEM BIOS 2.7 支持 Windows Server 2025

VMware ESXi 6.7U3u macOS Unlocker & OEM BIOS 2.7 集成 Realtek 网卡驱动和 NVMe 驱动 (集成驱动版) UI fix 此版本解决的问题&#xff1a;VMware Host Client 无法将现有虚拟磁盘 (VMDK) 附加到虚拟机 请访问原文链接&#xff1a;https://sysin.org/blog/vmware-esxi-…