《C预处理器》PPT课件.ppt

上传人:za****8 文档编号:14488723 上传时间:2020-07-21 格式:PPT 页数:35 大小:520.51KB
返回 下载 相关 举报
《C预处理器》PPT课件.ppt_第1页
第1页 / 共35页
《C预处理器》PPT课件.ppt_第2页
第2页 / 共35页
《C预处理器》PPT课件.ppt_第3页
第3页 / 共35页
点击查看更多>>
资源描述
,程序设计基础,程序设计基础 The C Programming Language,本章要点,文件包含 宏替换 条件包含,C预处理器,C语言通过预处理器提供了一些语言功能,从概念上讲,预处理器是编译过程中单独执行的第一个步骤。 include 指令和define指令是两个最常用的预处理器指令。预处理器指令的特点如下: 以“#”开头; 占单独书写行; 语句尾不加分号。,一、实例导入,例7.1 写出下列程序段的运行结果。,#define A 10 #define B A-2 printf(%d,%d,%d,%d, A, B, B*2, B*3);,提示:,宏定义中也可以使用前面出现的宏定义。,一、文件包含,文件包含指令(即#include指令)使得处理大量的#define指令以及声明更加方便。 在源文件中,任何形如: #include 文件名 或 #include 的行都将被替换为由文件名指定的文件的内容。,文件包含,如果文件名用引号引起来,则在源文件所在位置查找该文件;如果在该位置没有找到文件,或者如果文件名是用尖括号括起来的,则将根据相应的规则查找该文件,这个规则同具体的实现有关。 被包含的文件本身也可包含#include指令。,文件包含,源文件的开始处通常都会有多个#include指令,它们用以包含常见的#define语句和extern声明,或从头文件中访问库函数的函数原型声明,比如。 #include指令是将所有声明捆绑在一起的较好的方法。它保证所有的源文件都具有相同的定义与变量声明,这样可以避免出现一些不必要的错误。很自然,如果某个包含文件的内容发生了变化,那么所有依赖于该包含文件的源文件都必须重新编译。,文件包含,#include 指令能够实现多文件的组织。如果程序的各组成部分很长,可以把该程序分割到若干个源文件中。之所以分割成多个文件,主要是考虑在实际的程序中,它们分别来自于单独编译的库。分割时,必须考虑定义和声明在这些文件之间的共享问题,尽可能把共享的部分集中在一起,这样就只需要一个副本,修改程序时也容易保证程序的正确性。 总之,对于某些中等规模的程序,最好只用一个头文件存放程序中各部分共享的对象。较大的程序需要使用更多的头文件,我们需要精心地组织这些头文件。,二、宏替换,宏定义的形式如下: #define 名字 替换文本 这是一种最简单的宏替换,后续所有出现名字记号的地方都将被替换为替换文本。 #define指令中的名字与变量名的命名方式相同。#define指令定义的名字的作用域从其定义点开始,到被编译的源文件的末尾处结束。,宏替换,通常情况下,#define指令占一行,但也可以把一个较长的宏定义分成若干行,这时需要在待续的行末尾加上一个反斜杠。替换文本是#define指令行尾部的所有剩余部分内容,它可以是任意字符串,如: #define forever for( ; ; ) /*无限循环*/ 该语句为无限循环定义了一个新名字forever。替换只对记号进行,对括在引号中的字符串不起作用。,宏替换,宏定义也可以带参数,这样可以对不同的宏调用使用不同的替换文本。例如,下列宏定义定义了一个宏max: #define max(A, B) (A)(B)?(A):(B) 因此,语句: x=max(p+q, r+s); 将被替换为下列形式: x=(p+q)(r+s)?(p+q):(r+s); 注意,要适当使用圆括号以保证计算次序的正确性。,例7.2 写出下列程序段的运行结果。,#define f(a, b, x) a*x+b printf(%d, %dn, f(3, 2, 1), f(6, 5, f(3, 2, 1);,宏替换,作为参数的表达式有时会重复计算,如果表达式存在副作用(比如含有自增运算符或输入/输出),则会出现不正确的情况。 但是,宏还是很有价值的。头文件中有一个很实用的例子:getchar与putchar函数在实际上中常常被定义为宏,这样可以避免处理字符时调用函数所需的运行时开销。头文件中定义的函数也常常是通过宏实现的。,宏替换,可以通过#undef指令取消名字的宏定义,这样做可以保证后续的调用是函数调用,而不是宏调用。 形式参数不能用带引号的字符串替换。但是,如果在替换文本中,参数名以#作为前缀则结果将被扩展为由实际参数替换该参数的带引号的字符串。,例如:,#define dprint(expr) printf(#expr =%gn, expr) 使用语句 dprint(x/y); 调用该宏时,该宏将被扩展为: printf(x/y =%gn, x/y); 其中的字符串被连接起来了,这样,该宏调用的效果等价于 printf(x/y =%gn, x/y);,预处理器运算符#,预处理器运算符#为宏扩展提供了一种连接实际参数的手段。如果替换文本中的参数与#相邻,则该参数将被实际参数替换,#与前后的空白符将被删除,并对替换后的结果重新扫描。,例如:,#define paste(front, back) front # back 因此,宏调用paste(name, 1)的结果将建立记号name1。 #的嵌套使用规则比较难以掌握。,三、条件包含,可以使用条件语句对预处理本身进行控制,这种条件语句的值是在预处理执行的过程中进行计算。 这种方式为在编译过程中根据计算所得的条件值选择性地包含不同代码提供了一种手段。,条件包含有三种形式:,#ifdef 标识符 程序段1 #else 程序段2 #endif,#ifndef 标识符 程序段1 #else 程序段2 #endif,#if 表达式 程序段1 #else 程序段2 #endif,(1),如果标识符已被 #define 命令定义过,则对程序段1 进行编译;否则对程序段2进行编译。 如果没有程序段2(它为空),本格式中的#else可以缺省。,#ifdef 标识符 程序段1 #else 程序段2 #endif,(2),与第一种形式的区别是: 将“ifdef”改为“ifndef”。它的功能是: 如果标识符未被#define命令定义过则对程序段1进行编译,否则对程序段2进行编译。 如果没有程序段2(它为空),本格式中的#else可以缺省。,#ifndef 标识符 程序段1 #else 程序段2 #endif,(3),如常量表达式的值为真(非0),则对程序段1进行编译,否则对程序段2进行编译。因此可以使程序在不同条件下,完成不同的功能。 本格式中的#else通常不可以缺省。,#if 表达式 程序段1 #else 程序段2 #endif,条件包含,#if语句对其中的常量整型表达式(其中不能包含sizeof、类型转换运算符或enum常量)进行求值,若该表达式的值不等于0,则包含其后的各行,直到遇到#endif、#elif或#else语句为止(预处理器语句#elif类似于else if)。 在#if语句中可以使用表达式defined(名字),该表达式的值遵循下列规则:当名字已经定义时,其值为1;否则,其值为0。,说明:,条件编译语句#if中不能使用sizeof,因为预处理器不对类型名进行分析。但预处理器并不计算#define语句中的表达式,因此,在#define中使用sizeof是合法的。,例如:,为了保证hdr.h文件的内容只被包含一次,可以将该文件的内容包含在下列形式的条件语句中: #if !defined(HDR) #define HDR /* hdr.h文件的内容放在这里 */ #endif,或者,上面有关#if的例子可以改写为下列形式: #ifndef HDR #define HDR /* hdr.h文件的内容放在这里 */ #endif,本章小结,参考书目,http:/cm.bell- http:/www.cs.bell-,网络资源, (罗朝盛个人网站) http:/cpp.ga- (蚂蚁的C/C+标准编程 ) (浙大精品课程) http:/www.sandroid.org/TurboC/ (History) ,讨 论 时 间,相关网站,判题系统: http:/10.132.254.54 作业上传: ftp:/10.132.243.2,
展开阅读全文
相关资源
相关搜索

最新文档


当前位置:首页 > 图纸专区 > 课件教案


copyright@ 2023-2025  zhuangpeitu.com 装配图网版权所有   联系电话:18123376007

备案号:ICP2024067431-1 川公网安备51140202000466号


本站为文档C2C交易模式,即用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知装配图网,我们立即给予删除!