(10)-7.第七章 预处理命令程序设计基础_第1页
(10)-7.第七章 预处理命令程序设计基础_第2页
(10)-7.第七章 预处理命令程序设计基础_第3页
(10)-7.第七章 预处理命令程序设计基础_第4页
(10)-7.第七章 预处理命令程序设计基础_第5页
已阅读5页,还剩22页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第七章预处理命令7.1宏定义7.2文件包含7.3条件编译C语言的重要功能,它由预处理程序负责完成,是C语言区别于其他高级语言的又一特征。预处理语句都以#开始。合理使用预处理功能可以使程序员更容易地开发程序,也使开发出来的程序易于阅读、修改、调试和移植,有利于模块化程序设计技术的实现。

7.1宏定义定义:用#define指定的标识符表示一个字符串被称为宏定义。指定的标识符称为宏(Macro)或宏名,宏名所代表的字符串称为宏体。功能:宏定义位置以后的所有宏名标识符都将用宏体字符串替代,这一过程称为宏代换、宏替换或宏展开。宏定义≠宏代换:宏定义由宏定义命令完成,宏代换由预处理程序自动完成。7.1.1无参宏定义宏定义的格式:#define宏名宏体宏调用的方法:在非字符串内用宏名代表宏体字符串的操作。宏替换的过程:对宏定义后的程序代码,用宏体替换所有宏名标识符的过程。宏体的本质:字符符号串。它可以由数值型常数、表达式和格式串等构成。宏的运用情景:可以对程序中反复使用的表达式或程序代码段进行宏定义。例如:#defineM

(n*n+3*n)宏定义后,M代表串“(n*n+3*n)”;此后,源程序代码中非字符串内的所有表达式串“(n*n+3*n)”在书写上都可用宏名M代替。在对源程序进行编译预处理时,将先用"(n*n+3*n)"表达式串去置换源程序中的所有宏名符号M,再进行编译。例7-1宏替换实例。#include<stdio.h>#defineM(n*n+3*n)

/*用"(n*n+3*n)"替换M宏名*/intmain(void){intnResult,n; printf("inputanumber:"); scanf("%d",&n); nResult=3*M+4*M+5*M;/*所有M宏名将被替换*/ printf("nResult=%d\n",nResult); return0;}/*Endofmain()*/宏定义宏调用宏展开:3*(n*n+3*n)+4*(n*n+3*n)+5*(n*n+3*n)

注意:宏定义无括号时,展开结果为:

3*n*n+3*n+4*n*n+3*n+5*n*n+3*n;

该表达式虽然语法无误,但与前一结果表达式的逻辑含义不一致。宏定义应保证在宏替换不要发生语法错误,也不要发生逻辑错误。宏展开只是简单的符号串替换。若宏体为表达式,两边的括号不能少。宏定义行的行末不能加分号。否则,分号属于宏体字符串。宏名和宏体间可有多个空格字符,但宏体串以新行开始为终止。宏体串超过一行时,可用续行命令('\')接续。宏定义既可以在函数体外,也可以在函数体内。但最好在函数体外。宏的默认作用域为宏定义命令行到源程序文件末尾。要人为终止宏的作用,可在终止位置处用#undef预处理命令标记。注意:取消宏定义PI,终止#definePI3.14159的宏替换作用注意:当用#undefPI终止了PI的作用后,宏名PI即无效。在后面的源程序代码中,PI符号名可以被重新定义或作它用。例7-2宏定义的作用域。#definePI3.14159intmain(void){……}#undefPIfunc1().......宏名引用若用双引号括住,预处理程序不对其作宏替换。宏定义允许嵌套,即在宏定义串中引用已定义过的宏名。在宏展开将层层代换。习惯上宏名用大写字母标识符表示,以区别于一般变量名。宏定义通常集中置于程序文件的开始或单独的一个文件中。宏名可表示数据类型,使书写方便或定制程序员习惯的程序编写习惯。有时,宏定义可减少书写麻烦。#defineOK100intmain(void){printf("OK");printf("\n");return0;}/*Endofmain()*/是字符串,不是宏名#definePI3.1415926#defineSPI*y*yintmain(void){……

printf("%f\n",S);……return0;}/*Endofmain()*/结果:3.1415926*y*y#defineINTEGERint#defineREALfloatintmain(void){INTEGERn1,n2;REALfA,fB;……return0;}/*Endofmain()*/代表数据类型#defineINTEGERint#defineREALfloat#defineBEGIN{#defineEND}#defineRETreturn0#defineMAIN_SUBmain(void)#defineNOTE_B/*#defineNOTE_E*/INTEGERMAIN_SUBBEGININTEGERn1,n2;REALfA,fB;……RET;END

NOTE_BEndofmain()NOTE_E定制代码书写习惯

7.1.2带参宏定义*宏定义格式:#define宏名(形参表)宏体

宏调用格式:宏名(实参表);带参宏的形参和实参:宏定义中的参数称为形式参数,宏调用中的参数称为实际参数。带参数的宏在宏展开时要用实参符号串去替代宏体中的形参符号串。带参的宏又被称为函数宏(Function-macro)。例7-6带参数的宏定义和宏调用方法。

#defineM(n)n*n+3*n……k=M(5);……k=5*5+3*5;例7-7带参数的宏定义和宏调用。#include<stdio.h>#defineMAX(num1,num2)

\(num1>num2)?num1:num2intmain(void){intm,n,max;

printf("Inputtwonumbers:");

scanf("%d%d",&m,&n);max=MAX(m,n);

printf("max=%d\n",max);return0;}/*Endofmain()*/运行结果:Inputtwonumbers:23max=3max=(m>n)?m:n带参宏的意义由宏调用展开后的场景决定。对带参宏定义的几点说明:宏名和形参表之间不能有空格出现。函数调用与宏调用的区别:函数的形参和实参是两个不同的实体,各有自己的数据类型、存储空间和作用域。调用时把实参值赋予形参以进行值传递。形参在函数调用前不分配存储空间,但执行调用时必须分配与声明类型一致的内存空间,以存放由实参空间中传递来的参数值。带参宏不存在存储空间的分配。参数在宏调用中的作用与宏名一样,只是作简单的符号替换,不是值传递。从函数调用和宏调用的时间有效性看:函数是在执行时进行虚实结合,宏是在预处理时进行代码级的替换与展开。可见,函数是在编译连接后的执行期开始作用,带参宏展开是在编译之前完成。#include<stdio.h>#defineMAX

(num1,num2)

\(num1>num2)?num1:num2intmain(void){intm=2,n=7;

printf("m=%dn=%dMAX=%d\n",\

m,n,MAX(m,n));return0;}/*Endofmain()*/宏名和形参表之间不能有空格宏替换结果:(num1,num2)(num1>num2)?num1:num2(m,n)宏替换使printf()调用非法时,会出现编译错误!#include<stdio.h>#definePRINT1

printf("m=%dn=%d\n",m,n);\m++;n++;printf("OK\n");#definePRINT2

printf("m=%dn=%d\n",m,n);\

printf("OK…OK");intmain(void){intm=2,n=7;

printf("\n");PRINT1;PRINT2;return0;}/*Endofmain()*/宏体是指宏名以后直到宏定义行结束前的所有字符(包含续行内容)m=2n=7OKm=3n=8OK…OK例7-8带参宏定义、宏调用与函数定义、函数调用的区别。#defineSQ(n)(n)*(n)intsquare(intnumber){return(number*number);}/*Endofsquare()*/intmain(void){intm,nSquare;

printf("Inputanumber:");

scanf("%d",&m);

nSquare=SQ(m+1);

printf("nSquare=%dsquare=%d\n",nSquare,\square(m+1));return0;}/*Endofmain()*/宏定义中的形参是标识符宏调用中的实参是任何合法表达式宏替换结果:nSquare=(m+1)*(m+1);函数调用结果:square(4)可见:宏替换实参表达式时不做计算,只是将实参表达式作为一个符号串直接对宏体中的形参名进行符号串的原样替换。函数调用是把表达式的值计算出来,将其传送到形参所在的存储空间中去。运行结果如下:Inputanumber:3nSquare=16square=16#include<stdio.h>#defineSQ(n)

n*nintsquare(intnumber){return(number*number);}/*Endofsquare()*/intmain(void){intm,nSquare;

printf("Inputanumber:");

scanf("%d",&m);

nSquare=SQ(m+1);

printf("nSquare=%dsquare=%d\n",nSquare,\square(m+1));return0;}/*Endofmain()*/宏替换结果:nSquare=m+1*m+1;运行结果如下:Inputanumber:3nSquare=7square=16尽量用圆括号对括住宏体中的形参,甚至于整个宏体,以免出错。有时,仅将宏体中的形参符号括住还不够。需要将整个宏体串括住。这需要程序设计者仔细斟酌宏名出现的上下文环境。#include<stdio.h>#defineSQ(n)

(n)*(n)intmain(void){intm,nSquare;

printf("Inputanumber:");

scanf("%d",&m);

nSquare=160/SQ(m+1);

printf("nSquare=%d\n",nSquare);return0;}/*Endofmain()*/宏替换结果:nSquare=160/(m+1)*(m+1);运行结果如下:Inputanumber:3nSquare=160(1)求给定数平方的函数实现法#include<stdio.h>/*exam0711a.c*/intsquare(intnumber){return((number)*(number));}/*Endofsquare()*/intmain(void){inti=1;while(i<=5)printf("%d\n",square(i++));return0;}/*Endofmain()*/例7-11在表达式计算中,带参宏调用与函数调用的差异。传值形式的函数调用结果如下:1491625(2)求给定数平方的宏替换实现法#include<stdio.h>/*exam0711b.c*/#defineSQ(n)((n)*(n))intmain(void){inti=1;while(i<=5)

printf("%d\n",SQ(i++));return0;}/*Endofmain()*/符号替换的宏调用:((i++)*(i++))结果如下:21230文件包含是C语言进行模块化程序设计的重要手段。它将公用性强的宏定义、数据结构或函数声明等内容提炼出来构成一个单独文件,在需要的程序模块头部包含进去。一般格式为:#include"路径\文件名"|<路径\文件名>功能:把指定的文件内容插入该命令行位置以取代该命令行,使指定文件和当前源程序文件连成一体。

7.2文件包含#include中的文件名可以用双引号或尖括号括起来。尖括号对表示在系统默认的包含文件目录中去查找(它由用户设置)。双引号对表示先在源程序所在的文件目录中查找,若未找到,再到系统默认的包含文件目录中查找。通常,<>表示标准的include目录之头文件,""表示与当前应用程序相关的用户定义文件。一个#include只能指定一个被包含文件。文件的包含允许嵌套。对于文件包含的几点说明:功能:如果宏名标识符已被#define定义过,就对程序段1进行编译;否则对程序段2进行编译。没有程序段2时,变成用左边的形式。

7.3

条件编译*条件编译使编译器根据不同条件编译不同代码段,以产生不同目标代码文件。这对于程序的多环境移植和调试是很有用的。第一种形式#ifdef宏名标识符程序段1#else

程序段2#endif#ifdef宏名标识符程序段#endif或例7-13条件编译示例。#include<stdio.h>#defineNUMokintmain(void){structstu{intnNum;char*sName;charcSex;floatfScore;}*ps;……

#ifdefNUM

printf("Number=%d\nnScore=%f\n",ps->nNum,ps->fScore);#else

printf("Name=%s\nSex=%c\n",ps->sName,ps

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论