第12章 编译预处理 12.1 了解编译预处理 12.2 宏 定 义 12.3 文 件 包 含 12.4 条 件 编 译.

Slides:



Advertisements
Similar presentations
第五节 函数的微分 一、微分的定义 二、微分的几何意义 三、基本初等函数的微分公式与微分运算 法则 四、微分形式不变性 五、微分在近似计算中的应用 六、小结.
Advertisements

2.8 函数的微分 1 微分的定义 2 微分的几何意义 3 微分公式与微分运算法则 4 微分在近似计算中的应用.
第五章 二次型. 第五章 二次型 知识点1---二次型及其矩阵表示 二次型的基本概念 1. 线性变换与合同矩阵 2.
二级指针与二维数组.
Tool Command Language --11级ACM班 金天行.
6.4 字符串与指针 1. 用字符数组存放一个字符串.
C++中的声音处理 在传统Turbo C环境中,如果想用C语言控制电脑发声,可以用Sound函数。在VC6.6环境中如果想控制电脑发声则采用Beep函数。原型为: Beep(频率,持续时间) , 单位毫秒 暂停程序执行使用Sleep函数 Sleep(持续时间), 单位毫秒 引用这两个函数时,必须包含头文件
在PHP和MYSQL中实现完美的中文显示
第九章 字符串.
EBNF与操作语义 请用扩展的 BNF 描述 javascript语言里语句的结构;并用操作语义的方法描述对应的语义规则
4.3函数 4.3.1函数的概念及定义 1、函数的概念: 可以被其它程序调用具有 特定功能的一段相对独立的 程序(模块),称函数。
授课老师:龚涛 信息科学与技术学院 2018年3月 教材:《Visual C++程序员成长攻略》 《C++ Builder程序员成长攻略》
第13章 编译预处理 宏定义 文件包含 条件编译.
SISO 2011级 C语言复习指导 灰色部分不需要复习 1.
第 十 章 指 针.
第10章 预处理过程 一、编译预处理指令概述 二、预处理指令 #include 三、#define指令.
走进编程 程序的顺序结构(二).
辅导课程六.
元素替换法 ——行列式按行(列)展开(推论)
第一单元 初识C程序与C程序开发平台搭建 ---观其大略
1.2 MATLAB变量表达式与数据格式 MATLAB变量与表达式 MATLAB的数据显示格式
第二章 Java语言基础.
第五章 习题课 电子信息与计算机科学系 曾庆尚.
用event class 从input的root文件中,由DmpDataBuffer::ReadObject读取数据的问题
第八章 编译预处理 西安工程大学.
第一章 函数与极限.
C++语言程序设计 C++语言程序设计 第七章 类与对象 第十一组 C++语言程序设计.
第8章 编绎和预处理.
1.3 C语言的语句和关键字 一、C语言的语句 与其它高级语言一样,C语言也是利用函数体中的可执行 语句,向计算机系统发出操作命令。按照语句功能或构成的不 同,可将C语言的语句分为五类。 goto, return.
C语言程序设计 主讲教师:陆幼利.
EBNF与操作语义 请用扩展的 BNF 描述 javascript语言里语句的结构;并用操作语义的方法描述对应的语义规则
简单介绍 用C++实现简单的模板数据结构 ArrayList(数组, 类似std::vector)
$9 泛型基础.
C++语言程序设计 C++语言程序设计 第六章 指针和引用 第十一组 C++语言程序设计.
C程序设计 谭浩强 著 清华大学出版社.
程序设计基础A(C语言) 主讲教师: 许 康 教师主页:
线 性 代 数 厦门大学线性代数教学组 2019年4月24日6时8分 / 45.
微机原理与接口技术 微机原理与接口技术 朱华贵 2015年11月13日.
C语言程序设计 第九章 预处理命令.
计算机网络与网页制作 Chapter 07:Dreamweaver CS5入门
<编程达人入门课程> 本节内容 内存的使用 视频提供:昆山爱达人信息技术有限公司 官网地址: 联系QQ: QQ交流群: ,
C语言程序设计 第一章 数据类型, 运算符与表达式 第二章 顺序程序设计 第三章 选择结构程序设计 第四章 循环控制 第五章 数组.
项目二:HTML语言基础.
成绩是怎么算出来的? 16级第一学期半期考试成绩 班级 姓名 语文 数学 英语 政治 历史 地理 物理 化学 生物 总分 1 张三1 115
第六章 Excel的应用 一、Excel的单元格与区域 1、单元格:H8, D7, IV26等 2、区域:H2..D8, HS98:IT77
第4章 Excel电子表格制作软件 4.4 函数(一).
目录 8.1 宏定义 8.2 文件包含 8.3 条件编译 1.
第九节 赋值运算符和赋值表达式.
3.16 枚举算法及其程序实现 ——数组的作用.
本节内容 结构体 视频提供:昆山爱达人信息技术有限公司 官网地址: 联系QQ: QQ交流群 : 联系电话:
第8章 编译预处理 所谓编译预处理是指,在对源程序进行编译之前,先对源程序中的编译预处理命令进行处理;然后再将处理的结果,和源程序一起进行编译,以得到目标代码。 8.1 宏定义与符号常量 8.2 文件包含 8.3 条件编译 [Return]
C程序设计.
多层循环 Private Sub Command1_Click() Dim i As Integer, j As Integer
C++语言程序设计 C++语言程序设计 第六章 指针和引用 第十一组 C++语言程序设计.
2.6 字符型数据 一、 字符常量 1、字符常量的定义 用一对单引号括起来的单个字符,称为字符常量。 例如,‘A’、‘1’、‘+’等。
第9章 预处理命令.
第7章 模板 陈哲 副教授 南京航空航天大学 计算机科学与技术学院.
2019/5/21 实验一 离散傅立叶变换的性质及应用 实验报告上传到“作业提交”。 11:21:44.
本节内容 C语言的汇编表示 视频提供:昆山爱达人信息技术有限公司 官网地址: 联系QQ: QQ交流群 : 联系电话:
_03宽字符与Unicode编程 本节课讲师——void* 视频提供:昆山爱达人信息技术有限公司 官网地址:
本节内容 结构体.
复习 标签(label)、文本框(text)控件 按钮:点击事件
C++语言程序设计 C++语言程序设计 第一章 C++语言概述 第十一组 C++语言程序设计.
C++语言程序设计 C++语言程序设计 第九章 类的特殊成员 第十一组 C++语言程序设计.
基本知识 数据类型、变量、常量、运算符.
VFP的基本数据运算(一).
§4.5 最大公因式的矩阵求法( Ⅱ ).
<编程达人入门课程> 本节内容 有符号数与无符号数 视频提供:昆山爱达人信息技术有限公司 官网地址: 联系QQ:
编译原理实践 6.程序设计语言PL/0.
本节内容 this指针 视频提供:昆山爱达人信息技术有限公司 官网地址: 联系QQ: QQ交流群 : 联系电话:
Presentation transcript:

第12章 编译预处理 12.1 了解编译预处理 12.2 宏 定 义 12.3 文 件 包 含 12.4 条 件 编 译

12.1 了解编译预处理 C语言所提供的“编译预处理”功能是它区别于其他高级语言的又一重要特征,其主要功能包括三种:宏定义、文件包含和条件编译,分别由三种命令来实现。为了区别于C语句,预处理命令必须出现在一行的开始并以“#”号打头。

12.2 宏 定 义 宏定义由#define命令实现,根据实际应用的需要可以分为不带参数的宏定义和带有参数的宏定义两种命令形式。 12.2.1 不带参数的宏定义 命令的一般形式为: #define 标识符 字符串

定义中的“标识符”称为“宏名”。这一命令的作用仅仅是表明用指定的宏名来代替一个指定的字符串。例如: #define PI 3 .1415926 它的作用是指定用宏名PI来代替“3 .1415926”这个字符串。在预编译时,程序中所有出现“宏名”的地方,都将由这个字符串的内容进行替换,此过程称为“宏展开”。

说明 (1)不带参数的宏定义常常被用于定义符号常量。这样既可以提高程序的通用性,也便于修改。 例12.1 用宏名限定数组的大小。 #define N 10 /* 定义宏名N */ void ArrIn(int a[]) { int i;

for(i=0; i<N; i++) /* 为N个元素赋值 */ scanf("%d",&a[i]); } main( ) { int x[N]; /* 定义有N个元素的数组 */ ArrIn(x); …

以上是我们在编程中常用的方法:首先利用宏定义指定用N代表字符串10;所以主函数中定义的数组大小是10;函数ArrIn中读入的元素个数也是10。当需要改变数组大小时,只需改动#define命令行,而不用改动程序的其他部分。 (2)宏展开时系统不作语法检查,若定义不当,要待编译展开源程序时,才会引发错误。

例如: #define PI 3.141592b main( ) { float s, r=2.5; s=PI*r*r; printf("s=%f\n",s); }

程序中在定义代表值的宏名PI时,将字符串3 程序中在定义代表值的宏名PI时,将字符串3.1415926中的数字6误写作了字母b。这一宏定义命令本身并不构成错误。因为宏名PI代表的是字符串“3.141592b”,而不是数值。但在程序中引用了宏名PI来计算圆面积,赋值语句: s=PI*r*r;

经宏展开后变为: s=3.141592b*r*r; 从而导致编译出错。虽然出错位置在此赋值语句,但引发这一错误的根源还是上述宏定义命令。

(3)宏展开时,不对双引号括起来的字符串中的内容进行替换。如有定义: #define PI 3.14159 语句:printf("PI=%f\n",PI);中有2个PI,第一个PI是在双引号内的,它不被替换;第二个PI在双引号外,它将被展开成3.14159。

(4)在#define命令行中可以没有“字符串”,即表示成: 如: #define DEBUG 这里仅仅是为了表明标识符DEBUG已经“被定义”。这种定义形式在条件编译中将会用到。

(5)为了与变量名相区别,一般习惯用大写字母作宏名。但这不是规定,只是约定俗成。

12.2.2 带参数的宏定义 1.定义形式 #define 宏名(形参表) 字符串 例如: 12.2.2 带参数的宏定义 1.定义形式 #define 宏名(形参表) 字符串 例如: #define CYC(r) 2*3.14159*r

说明 (1)这里定义了一个计算圆周长的宏CYC(r),宏名CYC与其后的左括号之间不得留有空格,否则CYC将被视为不带参数的宏。 (2)作为替换文本的字符串中应含有括号中的参数,如2*3.14159*r中的r。否则,就没有必要定义带参数的宏。

(3)字符串中可以包含已经定义过的宏名。例如: #define CR "\n" #define D "%d" #define PRI D CR 则语句:printf(PRI, 20);执行后的输出结果为:20。

2.宏展开的过程 程序中若调用了带参数的宏,预编译时不仅仅是进行简单的字符串替换,还涉及到参数的替换。宏展开的过程是:按命令行中指定的字符串从左到右进行置换,遇到形参则以实参代替,对于非参数字符则原样保留。若有语句:

x=CYC(2.5); 宏展开时将用实参2.5替换字符串“2*3.14159*r”中的形参r,其他字符不变。置换后的语句为: x=2*3.14159*2.5;

说明 (1)由于宏定义是在预编译时展开的,它不具有任何计算功能。宏展开时,若实参是一个表达式,也是原样置换,而不进行求值。如有语句: y=CYC(3+5);

这里用实参3+5替换“2*3.14159*r”中的形参r后得到: y=2*3.14159*3+5; 而不是: y=2*3.14159*8; /* 3和5不能先做加法运算 */

(2)显然,为确保宏调用的正确性,在定义宏时,应将字符串中的形参用括号括起来。例如: #define CYC(r) 2*3.14159*(r) 这时将语句y=CYC(3+5);展开后为: y=2*3.14159*(3+5); 有时还需要在整个字符串外面加括号。如对于以下定义的计算两数之和的宏:

#define ADD(x,y) x+y 若宏调用形式为: k=2*ADD(3,4); 展开后为: k=2*3+4; 显然与设计意图不符,这时宏定义应改写作: #define ADD(x,y) (x+y)

3.带参数的宏与函数的主要区别 通过前面的举例,读者可能会觉得:在定义宏时有形参,通过宏调用给出实参,这种形式与函数的使用十分相似。事实上,它们是有本质不同的。主要体现在以下几方面。

(1)函数调用是在程序执行过程中进行的,要占用系统运行时间;宏展开是在预编译时进行的,不占用系统运行时间。 (2)函数调用时,要为形参开辟临时单元,有值的传递和返回;宏定义和宏展开时都不需要开辟内存单元,也没有值的传递和返回。

(3)函数调用时,作为实参的表达式是经过计算求值后传给形参的,因此要求实参和形参类型一致;而宏展开只是进行相应的参数及字符替换,并不对实参求值,所以不存在类型问题。 (4)宏展开会使源程序代码增长;而函数调用不影响源程序。 读者可根据上述带参数的宏与函数的区别,决定实际应用时的选取。

12.3 文 件 包 含 文件包含由#include命令实现,前面的章节中已多次出现。这一命令的一般形式为: #include "文件名" 12.3 文 件 包 含 文件包含由#include命令实现,前面的章节中已多次出现。这一命令的一般形式为: #include "文件名" 或 #include <文件名> 命令行中的“文件名”应该是C语言的源文件。在预编译时,系统将用指定文件名中的全部内容来替换此命令行。

12.4 条 件 编 译 通常,一个源程序中的所有非注释语句都要通过编译而形成目标代码,而C语言允许有选择的、只对源程序的某一部分进行编译。这就是所谓的“条件编译”。