第九章编译预处理 9、1宏替换 9、2文件包含 9、3条件编译 x
第九章 编译预处理 9、1 宏替换 9、2 文件包含 9、3 条件编译
9、1宏替换 不带参数的宏替换 1、格式:# define宏名宏体 其中宏名为C语言的标识符,一般用大写的字母表示。 2、用于将一个指定的标识符替换为一个字符串。 3、①、宏替换可提高程序的可读性,便于程序的修改 ②、在宏定义中还可以引用已定义的宏名。 ③、宏的作用域为定义该宏到本源文件结束。 ④、可以使用执 under处理命令结束宏的作用域。 x
9、1 宏替换 一、不带参数的宏替换 1、格式:#define 宏名 宏体 其中宏名为C语言的标识符,一般用大写的字母表示。 2 、用于将一个指定的标识符替换为一个字符串。 3、①、宏替换可提高程序的可读性,便于程序的修改。 ②、在宏定义中还可以引用已定义的宏名。 ③、宏的作用域为定义该宏到本源文件结束。 ④、可以使用#undef预处理 命令结束宏的作用域
带参数的宏替换 1、定义:# define宏名(形式参数表)宏体 2、引用:宏名(实际参数表) 3、对带参数的宏,不仅对宏名进行替换,而且对参数 进行替换。 例如:# include< stdio.h #tdefine pi 3. 14 #define circuit(r)2*PI*r #define area( r) Pi*r*r main float ra. c. a: scanf(n%f", &ra) c=circuit(ra) a=area (ra) printf(nra=%f, c=%f, a=%f ra, c, a);
二、带参数的宏替换 1、定义:#define 宏名(形式参数表) 宏体 2、引用:宏名(实际参数表) 3、对带参数的宏,不仅对宏名进行替换,而且对参数 进行替换。 例如:#include #define PI 3.14 #define circuit(r) 2*PI*r #define area(r) PI*r*r main() { float ra,c,a; scanf(“%f”,&ra); c=circuit(ra); a=area(ra); printf(“ra=%f,c=%f,a=%f”,ra,c,a);}
5、带参数的宏替换与函数有些相似,但有不同: 1)、宏替换产生的程序代码比使用函数时长。 2)、宏替换不需要进行参数传递、保护现场、等操 作其执行速度比函数快。 3)、宏替换不存在返回值类型和参数类型的问题。 4)、使用宏时应注意: A、定义宏时,最好对参数和宏体用括号括起来。 tH: #define square(n)n*n 调用时s= aquare(n+1) 则变成了s=a+1米a+1与预期效果不同。 B、定义带参数的宏时,宏名和左括号之间不能有空 格,否则被认为是无参数的宏 C、对宏的定义,只是进行字符的替换,不进行语法检 查
5、带参数的宏替换与函数有些相似,但有不同: 1)、宏替换产生的程序代码比使用函数时长。 2)、宏替换不需要进行参数传递、保护现场、等操 作其执行速度比函数快。 3)、宏替换不存在返回值类型和参数类型的问题。 4)、使用宏时应注意: A、定义宏时,最好对参数和宏体用括号括起来。 如:#define square(n) n*n 调用时 s=aquare(n+1) 则变成了s=a+1*a+1与预期效果不同。 B、定义带参数的宏时,宏名和左括号之间不能有空 格,否则被认为是无参数的宏. C、对宏的定义,只是进行字符的替换,不进行语法检 查
9、2文件包 1、指的是一个文件将另一个指定的源文件包含进去, 其一般形式为: # include<文件名 或# include文件名” 第一种形式:系统到系统标准目录中搜索该文件 第二种形式:首先到当前目录中搜索该文件,如找 不到则到系统标准目录中去搜索该文件 2、标准目录通常在编译系统的 include目录中, 3、编程时,用户可以编写自己的头文件,其中也可 以包含另外的头文件
9、2 文件包含 1、指的是一个文件将另一个指定的源文件包含进去, 其一般形式为: #include 或#include “文件名” 第一种形式:系统到系统标准目录中搜索该文件 第二种形式:首先到当前目录中搜索该文件,如找 不到则到系统标准目录中去搜索该文件。 2、标准目录通常在编译系统的include目录中, 3、编程时,用户可以编写自己的头文件,其中也可 以包含另外的头文件
例如:输入一个句子,统计单词个数。 首先编写一个头文件: if (iswhite(strid==TRUE) /* hong. h米/ n #include printf(whas %d words", n) #define true 1 #define false o 然后,编写程序,其中 包含该头文件: int iswhite(char c) #include"a: hong. h if(c=c='\n'c='\t') main return TRUE fint i, n=0 e⊥se char str[80] return FALSE; gets(str for(i=1; strli]!=\0' i++)
例如:输入一个句子,统计单词个数。 首先编写一个头文件: /*hong.h*/ #include #define TRUE 1 #define FALSE 0 然后,编写程序,其中 包含该头文件: #include "a:\hong.h" main() {int i,n=0; char str[80]; gets(str); for(i=1;str[i]!='\0';i++) if (iswhite(str[i])==TRUE) n++; printf(“has %d words",n); } int iswhite(char c) { if(c==''||c=='\n'||c=='\t') return TRUE; else return FALSE;}
9、3条件编译 利用条件编译可以实现只有条件满足时,才对源程序的某部 分进行编译。这样便于程序的移植。 其定义格式有: 1、# ifdef标识符 源程序部分1 # e⊥se 源程序部分2 fendi 当“标识符”已经被定义时,对源程序部分1进行编译, 否 则,对源程序部分2进行编译。 x
9、3 条件编译 利用条件编译可以实现只有条件满足时,才对源程序的某部 分进行编译。这样便于程序的移植。 其定义格式有: 1、#ifdef 标识符 源程序部分1 #else 源程序部分2 #endif 当“标识符”已经被定义时,对源程序部分1进行编译, 否 则,对源程序部分2进行编译
、# indef标识符 源程序部分1 #else 源程序部分2 #endif 当“标识符”没有被定义时,对源程序部分1进行编译,否 则对源程序部分2进行编译。 3、#if表达式 源程序部分 #else 源程序部分2 trendis 当“表达式”为真时,对源程序部分1进行编译,否则 对 源程序部分2进行编译
2、#ifndef 标识符 源程序部分1 #else 源程序部分2 #endif 当“标识符”没有被定义时,对源程序部分1进行编译,否 则对源程序部分2进行编译。 3、#if 表达式 源程序部分1 #else 源程序部分2 #endif 当“表达式”为真时,对源程序部分1进行编译,否则, 对 源程序部分2进行编译
对表达式的求值,只能对常量表达式进行求值。 如: void s sort(int all, int n) if(alj]>aLk]) lint i,j,k,t trendis for(I=0; I<n-1; I++) k= Ik=I t=alk for(j=I+1; j<n; j++) ak]=alll ifdef ascenD all=t if(ali]alk]) #else 如果再主程序中定义了宏 ASCEND则排序时按升序排列,否 则按降序排列
void s_sort(int a[],int n) {int i,j,k,t; for(I=0;Ia[k]) #endif k=j; t=a[k]; a[k]=a[I]; a[I]=t; } } 如果再主程序中定义了宏ASCEND则排序时按升序排列,否 则按降序排列