(40)--6.7 预处理(一)C语言程序设计基础.ppt
6.7 预处理(一)理(一)6.7.1 宏定宏定义 什么是什么是预处理理ANSI CANSI C标准规定可以在源程序中加入一些标准规定可以在源程序中加入一些“预处预处理命令理命令”,以以改进程序设计环境,提高编程效率改进程序设计环境,提高编程效率。在在对程序进行通常的编译之前,先对程序对程序进行通常的编译之前,先对程序中特殊中特殊的的命令进行命令进行“预处理预处理”。这些预处理命令是由这些预处理命令是由ANSI CANSI C统一规定的,但是它不是统一规定的,但是它不是C C语言本身的组成部分,不语言本身的组成部分,不能直接对它们进行能直接对它们进行编译。编译。预处理基本概念C语言编辑源程序源程序预处理后的理后的源程序源程序预处理预处理编译编译目目标程序程序链接链接可可执行程序行程序预处理命令理命令预处理基本概念C语言提供的提供的预处理命令主要包含以下预处理命令主要包含以下三种:三种:宏定义宏定义文件包含文件包含条件条件编译编译为了与一般语句相区别,这些命令以符号为了与一般语句相区别,这些命令以符号“”开头。开头。例如例如:#define#define#include#include 宏定宏定义命令命令预处理宏定义命令C语言标志:志:#define作用:定作用:定义符号常量和符号常量和带参的宏参的宏分分类:不不带参数的宏参数的宏带参数的宏参数的宏宏定宏定义命令命令不不带参数的宏定参数的宏定义一般形式为:definedefine 标识符标识符 字符串字符串示例:示例:define define PI 3.1415926PI 3.1415926定义时作用:用定义时作用:用指定的指定的标识符宏名标识符宏名PIPI来来代替宏体代替宏体“3.14159263.1415926”。宏宏替换替换:在程序编译前会用:在程序编译前会用宏体宏体替换程序中出现的所有替换程序中出现的所有宏名宏名。预处理宏定义命令C语言宏名宏体案例案例1:#include#define PI 3.1415926/*不不带参的宏定参的宏定义*/int main()float l,s,r,v;printf(input radius:);scanf(%f,&r);l=2.0*PI*r;s=PI*r*r;v=4.0/3*PI*r*r*r;printf(l=%10.4fns=%10.4fnv=%10.4fn,l,s,v);return 0;预处理宏定义命令C语言l=2.0*3.1415926*r;s=3.1415926*r*r;v=4.0/3*3.1415926*r*r*r;(1)(1)宏宏名一般名一般习惯用用大写字母大写字母表示,以便与表示,以便与变量名相量名相区区别,也也可可用小写字母用小写字母。宏名不分配占存宏名不分配占存储空空间,变量分配存量分配存储空空间。(2)(2)宏定宏定义不是不是语句,句,不必在行末加分号不必在行末加分号。如果加了分号。如果加了分号则会会连分号一起分号一起进行置行置换。(3)#define命令写在文件命令写在文件开开头,作用范,作用范围是从定是从定义位置开始到最位置开始到最后一行均有效。但后一行均有效。但可以用可以用undef命令命令终止宏定止宏定义的作用域的作用域。说明:明:预处理宏定义命令C语言示例:示例:#include#define PI 3.1415926int main()s=PI*r*r;void f1(int r)l=2*PI*r;在在f1f1函数中函数中,PIPI不不再代表再代表3.14159263.1415926。可以可以灵活控制宏定灵活控制宏定义的作用范围。义的作用范围。PI的的有效范有效范围C语言#undef PI PI的的有效范有效范围#include#include#define#define R 4.0 R 4.0#define define PI PI 3.1415926 3.1415926#define#define L 2*PI*R L 2*PI*R /*/*宏体中引用已经定义过的宏名宏体中引用已经定义过的宏名PIPI和和R*/R*/#define#define S PI*R*R S PI*R*R /*宏体中引用已经定义过的宏名宏体中引用已经定义过的宏名PIPI和和R*/R*/int int main()main()printfprintf(“L L=%10.4fn=%10.4fnS S=%10.4fn=%10.4fn,L L,S S););return 0;return 0;案例案例2:在:在宏定宏定义中可引用中可引用已定已定义的宏名。的宏名。预处理宏定义命令C语言用双撇号括起来的字符串用双撇号括起来的字符串内的字符,即使与宏名相内的字符,即使与宏名相同,也不同,也不进行置行置换宏宏名,要名,要进行宏替行宏替换预处理操作理操作预处理宏定义命令C语言#include#include#define#define R 4.0 R 4.0#define define PI PI 3.1415926 3.1415926#define#define L 2*PI*R L 2*PI*R#define#define S PI*R*R S PI*R*Rint int main()main()printfprintf(“L L=%10.4fnS=%10.4fn=%10.4fnS=%10.4fn,L L,S S););return 0;return 0;被替被替换为:2*3.1415926*4.0被替被替换为3.1415926*4.0*4.0作用:作用:不光进行字符串替换,还要进行参数替换。一般一般形式形式为:definedefine 宏名(参数表)宏名(参数表)字符串字符串 字符串中包含了括弧中所指定的参数宏定宏定义命令命令带参数的宏定参数的宏定义预处理宏定义命令C语言definedefine 宏名宏名(参数表参数表)字符串字符串示例:示例:#define S(a,b)a*b area=S(3,2);area=3*2area=3*2;宏定宏定义命令命令带参数的宏定参数的宏定义预处理宏定义命令C语言宏替换预处理带实参的参的宏替宏替换过程描述程描述u按按define命令行中指定的字符命令行中指定的字符串串从左到右从左到右进行置行置换。u若若串中包含宏中的形参(如串中包含宏中的形参(如a、b),),则将程序中相将程序中相应的的实参参(可以是(可以是常量、常量、变量或表达式量或表达式)代替形参代替形参。u若宏体中若宏体中的字符的字符不是不是参数的字符参数的字符(如(如*中的中的*号),号),则保留保留。预处理宏定义命令C语言案例案例3:写出运行结果:写出运行结果#include#define S(a)2*a*a/*定义了带参的宏定义了带参的宏*/int main()int m;m=S(5);printf(“m=%dn,m);return 0;预处理宏定义命令C语言m=2*5*5;运行结果为:m=50案例案例4:写出运行结果:写出运行结果#include#define S(a)2*a*a int main()int m;m=S(5);printf(“m=%dn,m);return 0;预处理宏定义命令C语言m=2*2+3*2+3;运行结果为:m=13m=S(2+3);案例案例5:写出运行结果:写出运行结果#include#define S(a)2*a*a int main()int m;m=S(2+3);printf(“m=%dn,m);return 0;预处理宏定义命令C语言m=2*(2+3)*(2+3);运行结果为:m=50#define S(a)2*(a)*(a)对带参数的宏替换只是将语句中的宏名后面括号内的实参参字符串代替字符串代替define 命令行中的形参形参。在宏定义时,在宏体中出现的除了参数以外的字符都会保留。注意:注意:预处理宏定义命令C语言函数函数调用要用要进行行参数的参数的传递及函数体内及函数体内语句的句的执行行;而;而带参的宏参的宏只是只是进行行简单的的字符替字符替换。函数函数调用是在用是在程序运行程序运行时处理理的,会的,会为形参分配形参分配临时的存的存储单元;元;而宏替而宏替换是是在在编译前前进行,行,在展开在展开时并不分配内存并不分配内存单元元,不,不进行行值的的传递处理,也没有理,也没有“返回返回值”的概念。的概念。函数要求函数要求实参参和形参和形参类型一致型一致;而;而宏名无宏名无类型型,参数,参数也无也无类型型,只是一只是一个符号代表个符号代表,替替换时代入指定的字符串即可。宏定代入指定的字符串即可。宏定义时,字符串字符串可以可以是任何是任何类型的数据。型的数据。调用用函数只可得到一个返回函数只可得到一个返回值,而用宏,而用宏可以得到可以得到几个几个结果果。带参数的宏和函数的区参数的宏和函数的区别:预处理宏定义命令C语言案例案例6 6:带参宏的应用:带参宏的应用#include#include#define#define PI PI 3.14159263.1415926#define CIRCLE(R,L,S,Vdefine CIRCLE(R,L,S,V)L L=2*PI*R;S=PI*R*R;V=4.0/3.0*PI*R*R*R=2*PI*R;S=PI*R*R;V=4.0/3.0*PI*R*R*Rintint main()main()float float r,l,s,v;r,l,s,v;scanf scanf(%f,&r);(%f,&r);CIRCLE(r,l,s,v CIRCLE(r,l,s,v););printf printf(r=%6.2f,l=%6.2f,s=%6.2f,v=%6.2fn,r,l,s,v(r=%6.2f,l=%6.2f,s=%6.2f,v=%6.2fn,r,l,s,v););return 0return 0;预处理宏定义命令C语言 l=2*3.1415926*r;s=3.1515926*r*r;v=4.0/3/0*3.1415926*r*r*r;案例案例6:带参宏的应用(宏替换后的程序):带参宏的应用(宏替换后的程序)#include int main()float r,l,s,v;scanf(%f,&r);l=2*3.1415926*r;s=3.1515926*r*r;v=4.0/3/0*3.1415926*r*r*r;printf(r=%6.2f,l=%6.2f,s=%6.2f,v=%6.2fn,r,l,s,v);return 0;预处理宏定义命令C语言1.预处理命令在程序编译前进行C语言中有3种预处理命令:宏定义、文件包含、条件编译2.宏定义命令不不带参的宏定参的宏定义带参的宏定参的宏定义预处理理时都是宏替都是宏替换,只是用宏体替,只是用宏体替换程序中的宏名程序中的宏名