当前位置:网站首页>程序环境和预处理
程序环境和预处理
2022-07-22 03:10:00 【Science52】
1. 程序的翻译环境和执行环境
在ANSI C的任何一种实现中,存在两个不同的环境。
第1种是翻译环境,在这个环境中源代码被转换为可执行的机器指令。
第2种是执行环境,它用于实际执行代码。
2. 详解编译+链接
2.1 翻译环境
组成一个程序的每个源文件通过编译过程分别转换成目标代码(object code)。
每个目标文件由链接器(linker)捆绑在一起,形成一个单一而完整的可执行程序。
链接器同时也会引入标准C函数库中任何被该程序所用到的函数,而且它可以搜索程序员个人 的程序库,将其需要的函数也链接到程序中。
1. 预处理 选项 gcc -E test.c -o test.i 预处理完成之后就停下来,预处理之后产生的结果都放在test.i文件中。
2. 编译 选项 gcc -S test.c 编译完成之后就停下来,结果保存在test.s中。
3. 汇编 gcc -c test.c 汇编完成之后就停下来,结果保存在test.o中。
2.3 运行环境
程序执行的过程: 1. 程序必须载入内存中。在有操作系统的环境中:一般这个由操作系统完成。在独立的环境中,程序 的载入必须由手工安排,也可能是通过可执行代码置入只读内存来完成。 2. 程序的执行便开始。接着便调用main函数。
3. 开始执行程序代码。这个时候程序将使用一个运行时堆栈(stack),存储函数的局部变量和返回 地址。程序同时也可以使用静态(static)内存,存储于静态内存中的变量在程序的整个执行过程 一直保留他们的值。
4. 终止程序。正常终止main函数;也有可能是意外终止。
3. 预处理详解
3.1 预定义符号
__FILE__ //进行编译的源文件
__LINE__ //文件当前的行号
__DATE__ //文件被编译的日期
__TIME__ //文件被编译的时间
__STDC__ //如果编译器遵循ANSI C,其值为1,否则未定义
3.2 #define
3.2.1 #define 定义标识符
3.2.2 #define 定义宏
#define 机制包括了一个规定,允许把参数替换到文本中,这种实现通常称为宏(macro)或定义 宏(define macro)。
下面是宏的申明方式: #define name( parament-list ) stuff 其中的 parament-list 是一个由逗号隔开的符号表,它们可能出现在stuff中。 注意: 参数列表的左括号必须与name紧邻。 如果两者之间有任何空白存在,参数列表就会被解释为stuff的一部分
2.2.3 #define 替换规则
在程序中扩展#define定义符号和宏时,需要涉及几个步骤。
1. 在调用宏时,首先对参数进行检查,看看是否包含任何由#define定义的符号。如果是,它们首先 被替换。
2. 替换文本随后被插入到程序中原来文本的位置。对于宏,参数名被他们的值所替换。
3. 最后,再次对结果文件进行扫描,看看它是否包含任何由#define定义的符号。如果是,就重复上 述处理过程。
注意: 1. 宏参数和#define 定义中可以出现其他#define定义的符号。但是对于宏,不能出现递归。 2. 当预处理器搜索#define定义的符号的时候,字符串常量的内容并不被搜索。
3.2.4 #和##
首先看一个案例
在这里不难发现这里的两个字符串会合并为一个字符串,接下来就可以利用这一点来看出其中的优点了
## 的作用
##可以把位于它两边的符号合成一个符号。 它允许宏定义从分离的文本片段创建标识符。
3.2.5 带副作用的宏参数
这一题就告诉大家,++这个操作符是有风险的
所以尽量不要用这些带有副作用的宏参数
3.2.6 宏和函数对比
1. 用于调用函数和从函数返回的代码可能比实际执行这个小型计算工作所需要的时间更多。 所以宏比函数在程序的规模和速度方面更胜一筹。
2. 更为重要的是函数的参数必须声明为特定的类型。 所以函数只能在类型合适的表达式上使用。反之这个宏怎可以适用于整形、长整型、浮点型等可以 用于>来比较的类型。
宏是类型无关的。
宏的缺点:当然和函数相比宏也有劣势的地方: 1. 每次使用宏的时候,一份宏定义的代码将插入到程序中。除非宏比较短,否则可能大幅度增加程序 的长度。 2. 宏是没法调试的。3. 宏由于类型无关,也就不够严谨。 4. 宏可能会带来运算符优先级的问题,导致程容易出现错。
3.2.7 命名约定
一般来讲函数的宏的使用语法很相似。所以语言本身没法帮我们区分二者。 那我们平时的一个习惯是: 把宏名全部大写 函数名不要全部大写
3.5 条件编译
在编译一个程序的时候我们如果要将一条语句(一组语句)编译或者放弃是很方便的。因为我们有条件 编译指令。
比如说: 调试性的代码,删除可惜,保留又碍事,所以我们可以选择性的编译。
常见的条件编译指令:
3.6.1 头文件被包含的方式:
1.本地文件包含
#include "filename"
这个是先到本地文件找,找不到再到库里面找
2.库文件包含
#include <filename>
库里找不到就报错
3.6.2 嵌套文件包含
#pragma once就可以避免头文件的重复引入。
本章到此结束,谢谢各位支持!
边栏推荐
- Exponential moving average method_ Baidu Encyclopedia
- C language outputs the number of all daffodils
- C语言实现在屏幕上打印特定的*星号图案
- C语言力扣第38题之外观数列。三种方法(遍历法、递归法与狼灭法)
- 统计,在sql中求每个部门的数据比值
- Autocomplete (autocomplete)
- 微服务真的不挑数据库吗?如何选择?
- MySQL workbench tutorial
- Product banner style type analysis
- Design of SKU database for commodity information
猜你喜欢
Check for degenerate boxes
With the advent of the meta universe era, how does soul Zhang Lu team create a new social experience?
ROS2自学笔记:TF坐标管理
Cookies and sessions
JS array object sorting (ES6)
[07] function call: why does stack overflow happen?
Pull daily activities, use cloud functions to send wechat applet subscription messages
GoldenSection
微服务真的不挑数据库吗?如何选择?
QT 动态dll的创建和调用
随机推荐
FPGA image processing learning face recognition
[fiddlertx plug-in] use Fiddler to capture Tencent classroom video download
Creation and call of QT dynamic DLL
AutoComplete(自动完成)
MySQL workbench tutorial
[C language - file] the data can finally be out of the memory. Go to the outside world to have a look / (o)/~~
【FiddlerTX插件】使用Fiddler抓包腾讯课堂视频下载
Ouu probiotics intensive cultivation of gastrointestinal health, award-winning tmall international Micro Ecological Innovation Conference
img.shape[-2:]/len(img.shape[-2:]):GeneralizedRCNN:original_image_sizes中的 torch._assert
Wechat applet realizes PDF preview function - pdf.js (including source code analysis)
北上广深杭30K试题:如何分配JVM内存模型?
JS advanced ES6 implementation inheritance
【一起学Rust】Rust学习前准备——注释和格式化输出
Joyous Torch Festival of the Yi Nationality
socket通信中select函数用法
Know garbage recycling
Zero basic learning canoe panel (2) -- control layout
别找了,全都帮你整理好了——SQL语句大全
面试刁钻问题应对思路
Product banner style type analysis