《C程序设计第九章》由会员分享,可在线阅读,更多相关《C程序设计第九章(23页珍藏版)》请在金锄头文库上搜索。
1、第九章 预处理命令,1 .掌握编译预处理的概念和特点;,2. 掌握“文件包含”的概念和使用;,3. 掌握不带参数的宏定义及其使用, 了解带参数的宏定义及其使用。,概 述,一、编译预处理的概念,C语言允许在程序中使用几种特殊的命令(它们不是一般的C语句),在C编译系统对程序进行通常的编译之前,先对程序中这些特殊命令进行“预处理”,然后将预处理的结果和源程序一起再进行通常的编译处理,以得到目标代码。,二、主要预处理功能,宏定义 ; 文件包含; 条件编译,一、不带参数的宏定义及宏替换,9.1 宏定义,宏名,宏内容,无分号,引例:,#define PI 3.1415926main() float l,
2、s,r,v; printf(“input radius :”); scanf(“%f”,其中 #define PI 3.1415926 作用是指定标识符PI来代表“3.1415926”,宏名用做代替一个字符串,不作语法检查;,宏定义的字符串不能以“;”结尾,字符串结束后一 定要换行;,宏定义的有效范围为定义之处到#undef命令终止, 如果没有#undef命令,则有效范围到本文结束;,C语言允许宏定义出现在程序中函数外面的任何 位置,但一般情况下它总写在文件的开头。,说明:,宏名一般习惯用大写字母,以便与变量名相区别;,在进行宏定义时,可以引用已定义的宏名;,说明:,宏替换由编译程序预先进行;
3、,宏替换范围是除字符串以外的所有宏名字;,若替换后文本串中仍含有宏名字,将再次进 行替换,直到程序中不含宏名字为止。,#define PI 3.1415926#define R 3.0#define L 2*PI*R#define S PI*R*R,第一次替换:printf(l=%f ns=%fn, 2*PI*R, PI*R*R);二:printf(l=%f ns=%fn, 2*3.1415926*3.0, 3.1415926*3.0*3.0);,main() printf(l=%f ns=%fn,L,S);,二、带参数的宏定义及宏替换,#define PI 3.1415926#define
4、S(r) PI*r*rmain()float r1=3.6, area;area=S(r1); /* S(r1)用PI*r1*r1替换 */printf(r=%f area=%fn,r1,area);,(1)对带参数的宏展开只是将语句中的宏名后面括号内的实参字符串代替#define命令行中的行参。(2)有时候为了得到正确结果,在字符串中的形式参数外面加一个括弧。(3)宏名与带参数的括弧之间不加空格,否则将空格以后的字符都作为替代字符串一部分。,例: define S_(r)_ PI*r*r area = S_(a);相当于: area = (r)_ PI*r*r_(a);,说明:,#defin
5、e PF(x) x*x /* #define PF(x) (x)*(x) */* #define PF(x) (x)*(x) */main() int a=2, b=3, c; c=PF(a+b)/PF(a+1); printf(nc=%d ,c);,按第一种宏定义:c=a+b*a+b/a+1*a+1;,按第二种宏定义:c=(a+b)*(a+b)/(a+1)*(a+1);,按第三种宏定义:c=(a+b)*(a+b)/(a+1)*(a+1);,注意替换时不求值,只是字符串的原样替换,例:分析程序写出结果.#define M3#define NM+2#define S(N)N*N*Nmain()
6、printf(“%dn”,S(N);,3+2*3+2*3+2,运行结果为:17,三、带参数的宏替换与函数的主要区别,函数调用时,先求出实参表达式的值,然后代入 形参。而使用带参的宏只是进行简单的字符替换。,函数调用是在程序运行时处理的,分配临时的内 存单元。而宏替换则是在编译时进行的,在展开 时并不分配内存单元,不进行值的传递处理,也 没有“返回值”的概念。,函数中函数名及参数均有一定的数据类型,而宏 不存在类型问题,宏名及其参数无类型。,宏替换不占运行时间,只占编译时间,而函数调 用则占运行时间。,#define MAX(x,y) xy?x:ymain()int n1,n2;float f1
7、,f2;scanf(%d%d%f%f,程序举例:,经预编译宏替换后的printf语句如下:,printf(maxi=%dmaxf=%f,n1n2?n1:n2, f1f2?f1:f2);,例:分析程序写出结果:#define PR printf#define NL “n”#define D “%d”#define D1 D NL#define D2 D D NL#define D3 D D D NL#define D4 D D D D NL#define S “%s”,main() int a,b,c,d; char str=“CHINA”; a=1,b=2,c=3,d=4; PR(D1,a);
8、 PR(D2,a,b); PR(D3,a,b,c); PR(D4,a,b,c,d); PR(S,str);,9.2 “文件包含”处理,C语言提供#include命令来实现“文件包含”的操作,其一般形式为:,#include “文件名”,#include ,或,作用:使编译系统把指定的被包含文件嵌入 到带有#include的源文件中。,“文件包含”示意图,file1.c file2.c file1.c 包含#include“file2.c” B A B A (a) (b) (c),1、一个#include命令只能指定一个被包含的文件,若要包含n个文件,应使用n个#include命令;2、若文件1
9、包含文件2,而文件2中要用到文件3的内容,则可在文件1中用2个#include命令分别包含文件2和文件3,而且文件3应出现在文件2之前,如下表示:file1.c#include “file3.h”#include “file2.h”.,3、文件包含可以嵌套。4、“”与在#include中的不同:使用时,系统只按指定的标准方式检索其他目录;一般用来调用库函数。使用“”时,系统若在源程序文件目录中找不到被包含的文件,则将按系统指定的标准方式检索其他目录;一般用来调用自定义文件。5、预编译后的被包含文件和其所在文件成为同一个文件,所有的全局静态变量将在整个文件中有效。,#include “文件名”,
10、先在当前工作目录中去查找,若找不到再到指定的标准目录中去查找。,如:对Turbo C编译系统,先在用户目录下 查找,然后在TCinclude文件夹中查找。,#include ,直接到系统指定的标准目录中去查找。,如:对Turbo C编译系统,直接在TCinclude 文件夹中查找。,9.3 条件编译,一、使用宏定义的标识符作为编译条件,作用:当所指定的标识符已经被#define 命令定义过,则在程序编译阶段只编译程序段1,否则编译程序段2。,作用:当所指定的标识符已经被#define 命令定义过,则在程序编译阶段只编译程序段1,,作用:当所指定的标识符未被#define 命令定义过,则在程序编
11、译阶段只编译程序段1,否则编译程序段2。,例1: #ifdef COMPUTER_A #define INTEGER_SIZE 16 #else #define INTEGER_SIZE 32 #endif,可用于实现程序在不同环境下的兼容性。,例2: #ifdef DEBUG printf(“x=%d,y=%dn”,x,y);#endif,可用于进行程序的调试。,调试过程中,在程序前面加#define DEBUG 调试完成后,将前面的#define DEBUG删除掉,二、使用常量表达式的值作为编译条件,作用:当所指定的表达式为真(非零)时就编译程序段1,否则编译程序段2。,可以事先给定一定条件,使程序在不同的条件下执行不同的功能。,程序举例:用同一程序实现大小写字母转换(若定义UP转换为大写),#include stdio.h#define UPmain() char s128; gets(s); #ifdef UP strupr(s); #else strlwr(s); #endifputs(s);,减少目标程序长度。减少运行时间。,