《C语言-第07章预处理.ppt》由会员分享,可在线阅读,更多相关《C语言-第07章预处理.ppt(28页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、第7章l 主要内容主要内容7.1 7.1 概述概述7.2 7.2 宏定义宏定义7.3“7.3“文件包含文件包含”处理处理7.1 概述概述 合理地使用预处理功能可以程序便于阅读、合理地使用预处理功能可以程序便于阅读、修改、移植和调试,也有利于模块华程序设修改、移植和调试,也有利于模块华程序设计。计。以以“#”号开头的预处理命令,如号开头的预处理命令,如#include,宏定义命令宏定义命令#define等,这些预处等,这些预处理命令放在函数之外,一般放在源文件的前理命令放在函数之外,一般放在源文件的前面,称为预处理部分。面,称为预处理部分。7.2 宏定义宏定义7.2.1 无参宏定义无参宏定义宏定
2、义一般形式为宏定义一般形式为:define define 标识符标识符 字符串字符串例如:例如:define PI 3.1415926define PI 3.1415926宏定义的作用是在本程序文件中用指定的标识符PI来代替“3.1415926”这个字符串,在编译预处理时,将程序中在该命令以后出现的所有的PI都用“3.1415926”代替。这种方法使用户能以一个简单的名字代替一个长的字符串.这个标识符(名字)称为“宏名”在预编译时将宏名替换成字符串的过程称为宏替换或宏展开.define是宏定义命令。程序员输入的源程序程序员输入的源程序 预处理(宏替换)后的新源程预处理(宏替换)后的新源程序序#
3、include#define PI 3.1415926void 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.4fn,l);printf(s=%10.4fn,s);printf(v=%10.4fn,v);#include void main()float l,s,r,v;printf(input radius:);scanf(%f,&r);l=2.0*3.1415926*r;s=3.1415926*r*r;v=4.0/3*3.141
4、5926*r*r*r;printf(l=%10.4fn,l);printf(s=%10.4fn,s);printf(v=%10.4fn,v);(1)(1)宏名一般习惯用宏名一般习惯用大写字母大写字母表示,以便与变量名表示,以便与变量名相区别。但这并非规定,也可用小写字母。相区别。但这并非规定,也可用小写字母。(2)(2)使用宏名代替一个字符串,可以减少程序中重使用宏名代替一个字符串,可以减少程序中重复书写某些字符串的工作量。复书写某些字符串的工作量。宏定义是用宏名代宏定义是用宏名代替一个字符串,替一个字符串,只作简单置换,不作正确性检查只作简单置换,不作正确性检查。如有错误,只能在编译已被宏展
5、开后的源程序时如有错误,只能在编译已被宏展开后的源程序时发现。发现。(3)宏定义不是说明或语句,不必在行末加分号。如果加了分号则会连分号一起进行置换。(4)definedefine命令出现在程序中函数的外面,宏名的有效范围为定义命令之后到本源文件结束。通常,definedefine命令写在文件开头,函数之前,作为文件一部分,在此文件范围内有效。可以用 undefdef命令终止宏定义的作用域。#define G 9.8 _ void main()G的有效范围 -#undef G f1()在在f1f1函数中,不再代表函数中,不再代表9.89.8。这样可以灵活控制宏。这样可以灵活控制宏定义的作用范围
6、。定义的作用范围。(5)(5)宏名在源程序中若宏名在源程序中若用引号括起来用引号括起来,则预处理程序,则预处理程序不对其不对其作宏代换作宏代换。【例【例7.27.2】#define OK 100void main()printf(OK);printf(n);(6)(6)宏定义允许嵌套,在宏定义的字符串中宏定义允许嵌套,在宏定义的字符串中可以使用已经定可以使用已经定义的宏名义的宏名,在宏展开时由预处理程序层层代换。,在宏展开时由预处理程序层层代换。例如:例如:#define PI 3.1415926#define S PI*y*y对语句对语句printf(“%f”,S);在宏替换后变为:在宏替换
7、后变为:printf(“%f”,3.1415926*y*y);(7)(7)对对“输出格式输出格式”作宏定义,可以减少书定麻烦。作宏定义,可以减少书定麻烦。【例【例7.3】中就采用了(】中就采用了(7)那种方法。)那种方法。#include#define P printf#define D%dn#define F%fnvoid main()int a=5,c=8,e=11;float b=3.8,d=9.7,f=21.08;P(D F,a,b);P(D F,c,d);P(D F,e,f);执行结果:53.80000089.7000001121.080000 7.2.2 带参数的宏定义带参数的宏定
8、义 作用:作用:不是进行简单的字符串替换,还要进行不是进行简单的字符串替换,还要进行参数替换。参数替换。带参数的宏定义一般形式为带参数的宏定义一般形式为:define define 宏名(形参表)宏名(形参表)字符串字符串 其中:宏名同不带参的宏名,习惯用大写字母。形参表由一个或多个参数构成,注意形参与函数形参的区别:参数只有参数名,没有数据类型,只作替换,不分配内存空间。例如:#define M(y)y*y+3*yk=M(5);在宏调用时,用实参代替形参y,经预处理宏展开后的语句为:K=5*5+3*5程序员输入的源程序程序员输入的源程序 预处理(宏替换)后的新源程序预处理(宏替换)后的新源程
9、序#include#define MAX(a,b)(ab)?a:bvoid main()int x,y,max;printf(input two numbers:);scanf(%d%d,&x,&y);max=MAX(x,y);printf(max=%dn,max);#includevoid main()int x,y,max;printf(input two numbers:);scanf(%d%d,&x,&y);max=(xy)?x:y;printf(max=%dn,max);执行结果:Input two numbers:8 6Max=8(1)(1)带参的宏定义中,宏名和形参表之间不能有空
10、格出现。带参的宏定义中,宏名和形参表之间不能有空格出现。例如:例如:#define MAX(a,b)(ab)?a:b如果写为:如果写为:#define MAX (a,b)(ab)?a:b将为认为是无参定义,宏名将为认为是无参定义,宏名MAX代表字符串代表字符串 (a,b)(ab)?a:b。宏展开时,宏调用语句:。宏展开时,宏调用语句:max=MAX(x,y);将变为:将变为:max=(a,b)(ab)?a:b(x,y);(2)(2)函数调用是在程序函数调用是在程序运行时处理运行时处理的,为形参分配临的,为形参分配临时的内存单元。而宏展开则是在时的内存单元。而宏展开则是在编译前进行的编译前进行的
11、,在,在展开时并不分配内存单元,不进行值的传递处理,展开时并不分配内存单元,不进行值的传递处理,也没有也没有“返回值返回值”的概念。的概念。对函数中的对函数中的实参和形实参和形参类型要求一致参类型要求一致。而宏名无类型,它的。而宏名无类型,它的参数也无类参数也无类型,只是一个符号代表型,只是一个符号代表,展开时代入指定的字符串,展开时代入指定的字符串即可。宏定义时,即可。宏定义时,字符串可以是任何类型字符串可以是任何类型的数据。的数据。(3 3)在宏定义中的)在宏定义中的形参是标识符形参是标识符,而宏调用中的,而宏调用中的实实参可以是表达式参可以是表达式。【例【例7.5】表达式作为宏调用的实参
12、】表达式作为宏调用的实参 程序员输入的源程序程序员输入的源程序 预处理(宏替换)后的新源程预处理(宏替换)后的新源程序序#include#define SQ(y)(y)*(y)void main()int a,sq;printf(input a number:);scanf(%d,&a);sq=SQ(a+1);printf(sq=%dn,sq);#includevoid main()int a,sq;printf(input a number:);scanf(%d,&a);sq=(a+1)*(a+1);printf(sq=%dn,sq);执行结果:Input a number:5sq=36(4
13、)(4)在宏定义中,字符串内的形参通常要用括在宏定义中,字符串内的形参通常要用括号括起来以避免出错。在上例中的宏定义中号括起来以避免出错。在上例中的宏定义中(y)*(y)(y)*(y)表达式的表达式的y y都用括号括起来,因此结都用括号括起来,因此结果是正确的。如果去掉括号,把程序改为例果是正确的。如果去掉括号,把程序改为例7.67.6所示的形式。所示的形式。【例【例7.67.6】进行宏替换的一个典型例子进行宏替换的一个典型例子 程序员输入的源程序程序员输入的源程序 预处理(宏替换)后的新源程预处理(宏替换)后的新源程序序#include#define SQ(y)y*yvoid main()i
14、nt a,sq;printf(input a number:);scanf(%d,&a);sq=SQ(a+1);printf(sq=%dn,sq);#includevoid main()int a,sq;printf(input a number:);scanf(%d,&a);sq=a+1*a+1;printf(sq=%dn,sq);执行结果:Input a number:5sq=11(5)(5)带参的宏和带参函数很相似,但在本质上带参的宏和带参函数很相似,但在本质上是不同的,把同一表达式用函数处理与用宏是不同的,把同一表达式用函数处理与用宏处理两者的结果有可能是不同的。处理两者的结果有可能是
15、不同的。【例【例7.77.7】带参的函数和带参的宏的区别】带参的函数和带参的宏的区别 带参函数调用带参函数调用 带参的宏替换带参的宏替换#includevoid main()int SQ(int y);int i=1;while(i=5)printf(%dn,SQ(i+);int SQ(int y)return(y)*(y);#include#define SQ(y)(y)*(y)void main()int i=1;while(i=5)printf(%dn,SQ(i+);执行结果:1491625执行结果:1925其一般形式为其一般形式为:#include#include 文件名文件名 或或#include#include 7.3 文件包含文件包含一个include命令只能指定一个被包含文件,若隐若现多个文件要包含,则需用多个include命令。文件包含允许嵌套,即在一个被包含的文件中又可以包含另一个文件。
限制150内