版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、1,四、宏调用和内联函数 五、条件编译指令 六、字符串预处理操作符,第10章 预处理过程,2,四、宏调用和内联函数 宏调用是C语言编译器早已有之的,C+鉴于宏调用文 本参数类型上的缺陷,特地引进了内联函数。 宏调用并不真正是C语言的内在部分而是编译器对C语 言的重要充实,内联函数属于C+语言本身。 类似于带参的宏指令,内联函数在进行了类型匹配之 后将函数体的代码指令直接扩展于源程序的调用处。 宏调用比内联函数更易发生副作用,内联函数减少宏调 用的副作用。内联函数不能回避函数所固有的副作用,只是 将副作用约束到一处。,3,内联函数难以取代宏调用,宏调用展开是文本串的替 换,这种替换总被实际执行,
2、宏调用是更少中间环节的代码 展开形式。inline函数调用未必真的内联展开。 内联展开过程比宏调用付出多余的临时单元的代价。在 定义点仅由inline界定的函数是内部连接属性的。 预处理器中一些文本字符串操作符对于源程序的编写具 有莫大的好处, 而这些文本字符串操作符是编译阶段的内联 函数所无法直接利用的。宏调用无视参数的类型给通用参数 的程序编写提供了便利。例如前面介绍的交换两个内存数据 的SWAP宏: #define SWAP(a,b) temp=a; a=b;b=temp; 如果换成函数以匹配各种数据类型,则交换不同类型 变量或指针都应提供相关的函数。,4,例 带参的宏定义和内联函数 #
3、include #define MAX (a,b) (a) (b) ? (a) : (b) inline max (int a,int b) return ab ? a : b; void main (void) int b=2; int a=3; int c=MAX (a+,b+); printf (a=%d,b=%d,MAX (a,b)=%dn,a,b,c); b=4; a=3; c=MAX (a+,b); printf (a=%d,b=%d,MAX (a,b)=%dn,a,b,c); b=2; a=3; c=max (a+,b+); printf (a=%d,b=%d,max (a,b)
4、=%dn,a,b,c); b=2; a=3; c=max (a+,a+); printf (a=%d,b=%d,max (a,b)=%dn,a,b,c); ,5,宏调用: int c=MAX (a+,b+); 展开为: int c= (a+) (b+) ? (a+) : (b+); 根据三目条件运算符的路由机制(a+) (b+)先完成求 值计算,如果比较的结果为真执行其后的a+,否则执行 b+。三目表达式的结果就是后置运算表达式的结果即变化 前的值。因此对于a=3,b=2执行的结果是c=4,b=3,a=5。变 量a增值两次。 宏调用: c=MAX (a+,b); 展开为: c=(a+) (b)
5、 ? (a+) : (b); 对于b=4,a=3执行的结果是c=4,b=4,a=4。变量a增值一 次。内联函数调用: c=max (a+,b+);,6,vc 6.0编译器对于函数的虚实结合实参表达式的求值次 序为从右到左,如此就地展开为: int tb=b+; / 先对右边第一个实参进行类型匹配,tb=2 int ta=a+; / 后对左边第一个实参进行类型匹配,tb=3 c= ta tb ? ta : tb; /相当于c= 3 2 ? 3 : 2; 对于a=3,b=2执行的结果是c=3,b=3,a=4。变量a增值一 次。 类似地vc 6.0编译器对于内联函数调用:c=max(a+,a+);
6、可能展开为: int tb=a; int ta=a; a+; a+; c= ta tb ? ta : tb; 因此对于a=3,b=2执行的结果是tb=3;ta=3; 得到 c=3,b=2,a=5的输出结果。变量a增值二次。,7,五、条件编译指令 条件编译的作用有: 维护同一程序的不同版本,使源程序可适用不同的操作 系统,在程序的调试阶段可以使用条件编译指令放置一些显 示信息以便跟踪程序的错误或运行的动态情况,一旦程序正 常运行就可以重置条件编译的测试条件,使不关程序运行的 跟踪代码为编译器所忽略,达到注释掉程序段的目的。,8,条件编译指令有如下三种格式: 1. #if条件编译指令 (如果常量条
7、件表达式非零时编译) 条件编译指令 #if有下面三种不同的用法: (1) #if#endif条件编译指令 #if常量表达式 程序段 /当常量表达式的结果非零时,编译或保留程序段 #endif 预处理阶段的常量表达式是可以预先静态求值的由运算 符和整型常数枚举常数构成的整型表达式。sizeof(1)不是预 处理阶段的常量。-1+0 xab+!072*5/64=5+c是常量表达 式。,9,(2) #if#else #endif条件编译指令 #if常量表达式 程序段1 /当常量表达式1的结果非零时,编译或保留程序段1 #else 程序段0 /当常量表达式的结果为0时, 编译或保留程序段0 #endi
8、f (3) #ifelif#else #endif条件编译指令 #if常量表达式i 程序段i /当常量表达式i的结果非零时,编译或保留程序段i,10, #elif常量表达式k 程序段k /当常量表达式k的结果非零时,编译或保留程序段k . #elif常量表达式j 程序段j /当常量表达式j的结果非零时, 编译或保留程序段j . #else 程序段0 /当常量表达式的结果均为0时, 编译或保留程序段0 #endif,11,上面的程序段仅只有一个进入编译,C/C+预处理从上 到下测试每一条常量表达式的值,找到其中一条表达式非 零,就编译相应的程序段。 这类似于ifelse ifelse语句的执行情
9、况,在ifelse ifelse语句形式中仅执行非零条件下的复合语句。方括号包 括的内容表示可以省略的项目,只有 #if#endif是必不可少 的。 #endif指令是条件编译语法必须的伴生指令,只要使用 了#if、#ifdef和#ifndef就必须用结束条件块的#endif指令。,12,2. #ifdef条件编译指令( 如果标识符已定义则进行编译) 该指令使用下面两种等价的形式: #ifdef symbol program segment1 / if symbol is defined ,compile program segment1 #else program segment2 / if
10、 symbol is undefined ,compile program segment2#endif 或: #if defined(标识符) 程序段1 /标识符已经#define定义,编译或保留程序段1,13,#else 程序段2 /标识符未经#define定义或被#undef清除,编译或保留程序 /段2 #endif 上面方括号的项目表示可以省略的内容,defined是预 处理器操作符,其语法格式为: defined(标识符) 或 defined标识符 标识符已定义,defined(标识符)表达式的结果非零, 否则结果为0。defined预操作符用于#if#endif指令中,此 时标识符
11、的具体值并不重要,关键是标识符的定义与否。,14,3. #ifndef 条件编译指令(如果标识符未定义则进行编译) 该指令可以由上面格式 2的指令反向轮换1与2得到下面 两种等价的形式: #ifndef symbol program segment2 / if symbol is undefined ,compile program segment2 #else program segment1 / if symbol is defined ,compile program segment1 #endif 或: #if !defined(标识符) 程序段2,15,/标识符未经#define定义
12、或被#undef清除,编译程序段2 #else 程序段1 /标识符已经#define定义,编译程序段1 #endif 上面方括号的项目表示可以省略的内容,#ifndef的妙 用之处就是确保文件仅包含一次或标识符仅定义一次, 例如: #ifndef SYMBOL #include “symbol.h” #define SYMBOL #endif,16,#ifndef NULL #ifdef _cplusplus #define NULL 0 #else #define NULL (void *)0) #endif #endif,17,可以用条件编译预处理指令注释掉一些源代码,但又 容易将这些代码
13、恢复,这比用注释符“/*-*/”可以更有效的 控制程序段的去留。 下面的程序为了调试跟踪代码,运用了简单的编译预处理 指令,屏显语句printf可以酌情地予以去留。 预处理中的defined 操作符比#ifdef和#ifndef 具有更多 的用法,可以含逻辑表达式等。预处理指令的条件编译是确 定程序段的去留。 而流程控制ifelse ifelse语句经过预处理的筛选后则 用于实际地控制程序运行时的流程走向。两者的机制一致但 分工不同目标各异。,18,例 条件编译指令确定版本的交付 #include #define STUDY #define PROFESSION void main(void)
14、 #if defined(BRIEF) #endif /输出professional,19,六、字符串预处理操作符 1. 字符串操作符# 字符串操作符#的使用格式为: #s #宏形参 井字号#跟一个称为宏形参的标识名。字符串操作符组 合#s仅用于#define引入的宏定义中,旨在将相应的宏实参 转换为字符串常数。 例如:对于带参的宏定义 #define sout(s) cout#sendl 相应的宏调用: sout(this string is in double quote); 将导致宏展开: cout “this string is in double quote” endl;,20,例
15、字符串双引号展开 #include #define sout(s) cout#sendl #define dout(s,v) cout#svendl void main(void) sout ( this string is in double quote ); sout ( that string is in double quote ); sout ( the string include an escaped quote); dout ( cout#sendl; ,cout#sendl ); dout ( a=,10000 ); ,21,2. 字符合并操作符# 编译器本身可将相邻的字符串
16、合并, 例如: “ab-” “-cd”合并为“ab-cd” 字符合并操作符#提供更多的灵活性。其使用格式为: 文本#宏形参 例如: text#macro 合并为textmacro 字符串#字符串 例如: %d#%s 合并为%d%s 字符合并操作符#仅用于#define引入的带参的宏定义 中。 由于其用于将两个单独的标记合并为一个串联在一起的 文本串,双井字号#之前有操作数而其后跟宏形参名。,22,例如: #include #define showd(v,s) printf (- %d#s,v) #define shows(s,v) printf (#s#%s,v) void main (voi
17、d) shows(11 ,aaa); showd(22,bbb); /输出11aaa-22bbb,23,字符合并操作符#可用于有规律的对象名和函数名的 简化操作中。 如变量名序列: classt1 classt2 classt3 等可以宏定义为: #define object(type) class# type 这样: t1 object(t1); t2 object(t2); t3 object(t3); 就等价于定义变量: t1 classt1; t2 classt2; t3 classt3; 一般t1,t2和t3等是用户引入的类名序列。通过如此操 作,对象名或变量名具有强烈的规律性,便于程序统一的进 行字符处理,动态类型跟踪等。,24,例 字符合并操作符#进行动态类型跟踪 #include #define sout (s) cout#sendl #define dout (s,v) cout#svendl #define object (type) class#type void main (void) typedef short t1; t1 object(t1)=1; typedef long t2; t2 object(t2)=2; typedef double t3; t
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025梧州市第二职业中等专业学校工作人员招聘考试试题
- 2025来凤县中等职业技术学校工作人员招聘考试试题
- 2025杭州市第二机械技工学校工作人员招聘考试试题
- 市政工程高处作业施工方案
- 2026年零售智能营销创新报告
- 初中语文整本书阅读教学在提升学生文学素养中的研究课题报告教学研究课题报告
- 2026年日化健康法规政策报告
- 2026年智能马桶行业健康监测技术发展报告2026年
- 国常会聚焦海洋经济与科技创新;伊朗冲突外溢推升全球能源危机
- 纺织服饰行业运动鞋服2026Q1总结:Q1流水增长优异库存健康关注Q2假期消费表现
- 黑吉辽蒙2025年高考真题物理试卷【附答案】
- 2026年心理咨询师通关测试卷含完整答案详解(夺冠)
- 2026年浙江公务员考试行测真题及答案解析
- 2026中信证券总部暑期日常实习招聘笔试备考试题及答案解析
- 2025年凉山新华书店考试真题及答案
- 案例分析-垂体腺瘤 课件
- 基于知识本体的铁路工程EPC总承包项目风险管理研究
- 查缉战术课件大纲
- 3.辽宁2017定额宣贯《房屋建筑与装饰工程定额 》
- 抖音员工号申请在职证明参考模板
- LY/T 2422-2015薇甘菊防治技术规程
评论
0/150
提交评论