C语言程序设计-电子教案-朱建芳 第08章

上传人:E**** 文档编号:89423447 上传时间:2019-05-25 格式:PPT 页数:23 大小:93.01KB
返回 下载 相关 举报
C语言程序设计-电子教案-朱建芳 第08章_第1页
第1页 / 共23页
C语言程序设计-电子教案-朱建芳 第08章_第2页
第2页 / 共23页
C语言程序设计-电子教案-朱建芳 第08章_第3页
第3页 / 共23页
C语言程序设计-电子教案-朱建芳 第08章_第4页
第4页 / 共23页
C语言程序设计-电子教案-朱建芳 第08章_第5页
第5页 / 共23页
点击查看更多>>
资源描述

《C语言程序设计-电子教案-朱建芳 第08章》由会员分享,可在线阅读,更多相关《C语言程序设计-电子教案-朱建芳 第08章(23页珍藏版)》请在金锄头文库上搜索。

1、第 8章 编译预处理,本章学习目标 熟练掌握宏定义。 掌握文件包含处理。 了解条件编译。,Return,所谓编译预处理是指,在对源程序进行编译之前,先对源程序中的编译预处理命令进行处理;然后再将处理的结果,和源程序一起进行编译,以得到目标代码。,10.1 宏定义 10.2 文件包含 10.3 条件编译,10.1 宏定义,在语言中,“宏”分为无参数的宏(简称无参宏)和有参数的宏(简称有参宏)两种。,10.1.1 无参宏定义 1. 无参宏定义的一般格式 #define 标识符 语言符号字符串 其中:“define”为宏定义命令;“标识符”为所定义的宏名,通常用大写字母表示,以便于与变量区别;“语言

2、符号字符串”可以是常数、表达式、格式串等。,2. 使用宏定义的优点 (1)可提高源程序的可维护性 (2)可提高源程序的可移植性 (3)减少源程序中重复书写字符串的工作量,【例10-1】输入圆的半径,求圆的周长、面积和球的体积。要求使用无参宏定义圆周率。 /*exam10_1,输入半径,求圆的周长、面积和球的体积。*/ #include “stdio.h“ #define PI 3.1415926 main(void) double radius,length,area,volume; printf(“Input a radius: “); scanf(“%lf“, ,3说明 (1)宏名一般用大

3、写字母表示,以示与变量区别。但这并非是规定。 (2)宏定义不是语句,所以不能在行尾加分号。否则,宏展开时,会将分号作为字符串的1个字符,用于替换宏名。 (3)在宏展开时,预处理程序仅以按宏定义简单替换宏名,而不作任何检查。如果有错误,只能由编译程序在编译宏展开后的源程序时发现。 (4)宏定义命令#define出现在函数的外部,宏名的有效范围是:从定义命令之后, 到本文件结束。通常,宏定义命令放在文件开头处。,(5)在进行宏定义时,可以引用已定义的宏名。 例如: #define ONE 1 #define TWO ONE+ONE #define THREE ONE+TWO (6)对双引号括起来的

4、字符串内的字符,即使与宏名同名,也不进行宏展开。 例如: define XYZ this is a test printf(“XYZ“); 该语句不是打印输出: this is a test 而是打印输出: XYZ,演示,1带参宏定义的一般格式 #define 宏名(形参表) 语言符号字符串 2带参宏的调用和宏展开 (1)调用格式:宏名(实参表) (2)宏展开:用宏调用提供的实参字符串,直接置换宏定义命令行中、相应形参字符串,非形参字符保持不变。例如: #define MIN(a,b) (ab)?a:b main(void) int x, y; x=10;y=20; printf(“the m

5、inimum is: %d“ ,MIN(x,y); ,10.1.2 有参宏定义,当编译该程序时,由MIN(a,b)定义的表达式被替换, x和y用作操作数,即printf( )语句被代换后取如下形式: printf(“the minimum is: %d“ ,(xy)?x:y); 用宏定义代替实在的函数的一大好处是宏定义增加了代码的速度,因为不存在函数调用的开销。但增加速度也有代价:由于重复编码而增加了程序长度。,3说明: (1)在带参宏定义中,形式参数不分配内存单元,不做类型定义。宏调用时的实参代换形参不做类型检查。这是与函数不同的。利用宏不做类型检查的特性,在宏调用时避开数据类型的限制,来实

6、现某些函数无法实现的功能。如上例中的宏定义同样也可以用求两个实型数中的最小值,而如果改用函数实现则需要定义两个不同类型的函数。,(2)在带参宏定义中,宏名和形参表之间不能有空格出现。例如:把 #define MIN(a,b) (ab)?a:b 写为: #define MIN (a,b) (ab)?a:b 将被认为是无参宏定义,宏名MIN代表字符串(a,b) (ab)?a:b (3)在宏定义中形参是标识符,而宏调用中的实参可以是表达式。在宏调用中的实参是表达式时,可能引起意想不到的错误。,演示,例如,定义宏: #define AREA(r) 3.1416*r*r 在宏调用时按如下方式调用: k=

7、AREA(3+5); 则宏展开后形式为: k=3.1416*3+5*3+5; 计算结果与本来意图相差很远,所以在宏定义中,建议字符串内形参和整个字符串都用括号括起来以避免出错。如上述宏可以写为: #define AREA(r) (3.1416*(r)*(r) 这样定义后,实参是数据表达式也不会出错。,演示,(4)有参宏与有参函数的比较 不同之处,主要有以下几个方面: 1)调用有参函数时,是先求出实参的值,然后再复制一份给形参。而展开有参宏时,只是将实参简单地置换形参。 2)在有参函数中,形参是有类型的,所以要求实参的类型与其一致;而在有参宏中,形参是没有类型信息的,因此用于置换的实参,什么类型

8、都可以。有时,可利用有参宏的这一特性,实现通用函数功能。 3)使用有参函数,无论调用多少次,都不会使目标程序变长,但每次调用都要占用系统时间进行调用现场保护和现场恢复;而使用有参宏,由于宏展开是在编译时进行的,所以不占运行时间,但是每引用1次,都会使目标程序增大1次。,10.2 文件包含,1文件包含的概念 文件包含是指,一个源文件可以将另一个源文件的全部内容包含进来。 2文件包含处理命令的格式 include “包含文件名” 或 include 两种格式的区别仅在于: (1)使用双引号:系统首先到当前目录下查找被包含文件,如果没找到,再到系统指定的“包含文件目录”(由用户在配置环境时设置)去查

9、找。 (2)使用尖括号:直接到系统指定的“包含文件目录”去查找。一般地说,使用双引号比较保险。,一个大程序,通常分为多个模块,并由多个程序员分别编程。有了文件包含处理功能,就可以将多个模块共用的数据(如符号常量和数据结构)或函数,集中到一个单独的文件中。这样,凡是要使用其中数据或调用其中函数的程序员,只要使用文件包含处理功能,将所需文件包含进来即可,不必再重复定义它们,从而减少重复劳动。,3文件包含的优点,4说明 (1)编译预处理时,预处理程序将查找指定的被包含文件,并将其复制到#include命令出现的位置上。 (2)常用在文件头部的被包含文件,称为“标题文件”或“头部文件”,常以“h”(h

10、ead)作为后缀,简称头文件。在头文件中,除可包含宏定义外,还可包含外部变量定义、结构类型定义等。 (3)一条包含命令,只能指定一个被包含文件。如果要包含n个文件,则要用n条包含命令。 (4)文件包含可以嵌套,即被包含文件中又包含另一个文件。,/*exam10_2,演示时要分别存为3个相应的文件*/ /*minfile.c */ int min(int a,int b) return ab?a:b; 注意:在maxfile.c文件中也没有main()函数。,【例10-2】文件包含处理应用举例。以下程序是由3个文件组成的:minfile.c,maxfile.c和mainfile.c。,/*mai

11、nfile.c*/ #include “stdio.h” /*包含标准输入输出库函数*/ #include “maxfile.c” /*包含maxfile.c文件,以便调用max函数*/ #include “minfile.c” /*包含minfile.c文件,以便调用min函数*/ int main(void) int a=18,b=9,c,d; c=max(a,b); d=min(a,b); printf(“max=%d,min=%dn”,c,d); return 0; ,演示,注意:编译时使用“change dir”命令修改工作目录为3个文件的保存目录。,说明:虽然在mainfile.c

12、文件中没有定义max函数和min函数,但由于在mainfile.c文件中使用了#include “maxfile.c”和#include “minfile.c”包含命令,将这两个文件的内容包含到了mainfile.c源文件中,所以可以调用这两个函数。,10.3 条件编译,一般情况下,源程序中所有的行都参加编译。但有时希望对其中一部分内容只在满足一定条件才进行编译,这就是条件编译。商业软件公司广泛应用条件编译来提供和维护某一程序的许多顾客版本。,条件编译有以下几种形式: (1)ifdef 标识符 程序段1; else 程序段2; endif,功能:当“标识符”已经被#define命令定义过,则编

13、译程序段1,否则编译程序段2。 (1)在不同的系统中,一个int 型数据占用的内存字节数可能是不同的。这样往往需要对源程序作出修改,这就降低了程序的通用性。使用以下条件编译处理,则可以轻松解决此类问题。如:,如果在这组条件编译命令之前曾出现以下命令行: #define COMPUTER_A 0 或将COMPUTER_A定义为任何字符串,甚至是 #define COMPUTER_A 则编译后程序中的INTEGER_SIZE都用16代替,否则用32来代替。 这样源程序可以不必作任何修改就可以用于不同类型的计算机系统。,#ifdef COMPUTER_A #define INTEGER_SIZE 1

14、6 #else #define INTEGER_SIZE 32 #endif,如果COMPUTER_A在前面已经被定义过,则编译下面的命令行: #define INTEGER_SIZE 16 否则,编译下面的命令行: #define INTEGER_SIZE 32,(3) if 常量表达式 程序段1; else 程序段2; endif 功能:如果常量表达式的值为真(非0),则对程序段1进行编译,否则对程序段2进行编译。,(2) ifndef 标识符 程序段1; else 程序段2; endif 功能:当“标识符”没有被#define命令定义过,则编译程序段1,否则编译程序段2。与第一种形式的作用刚好相反,用法上两种形式差不多,使用时可根据需要任选一种。,【例10-3】设某程序的使用与语言有关,语言的信息存于相应的头文件中,采用条件编译识别与语言有关的信息。 #define LANGUAGE 1 #if LANGUAGE #include “china.h” #else #include “english.h” #endif,注意:条件编译当然也可以用条件语句来实现。但是用条件语句将会对整个源程序进行编译,生成的目标代码程序较长。而采用条件编译,则根据条件只编译其中的某一段程序,生成目标代码较短。,

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 高等教育 > 大学课件

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号