第10章 预处理命令_第1页
第10章 预处理命令_第2页
第10章 预处理命令_第3页
第10章 预处理命令_第4页
第10章 预处理命令_第5页
已阅读5页,还剩16页未读 继续免费阅读

下载本文档

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

文档简介

第10章预处理命令制作人:王敬华第10章:预处理命令

学习的意义

语言程序设计教程第二版第十章预处理命令CC语言的一个重要特征是它的预处理功能。我们知道,一个高级语言源程序在计算机上运行,必须先用编译程序将其翻译为机器语言。编译包括词法分析、语法分析、代码生成、代码优化等步骤,有时在编译之前还要做某些预处理工作,如去掉注释,变换格式等。C语言允许在源程序中包含预处理命令,在正式编译之前(词法分析之前)系统先对这些命令进行“预处理”,然后整个源程序再进行通常的编译处理。从语法上讲,这些预处理命令不是C语言的一部分,但使用它们却扩展了C语言程序设计的环境,可以简化程序开发过程,提高程序的可读性,也更有利于移植和调试C语言程序。本章主要介绍宏定义、文件包括和条件编译等预处理命令。学习的意义

源程序生成执行文件的过程:C语言源程序.c或.cpp编译目标程序.obj链接执行程序.exe#include<stdio.h>#definePI3.14159voidmain(){floatr=4;printf(“s=%f\n”,PI*r*r);}预处理命令预处理本章讨论之重点!语言程序设计教程第二版第十章预处理命令C学习目标

学习内容

预处理命令简介宏定义不带参数的宏定义带参数的宏定义文件包括条件编译本章小结掌握#include、#define、#if、#ifdef、#else、#ifndef和

#endif等命令的用法;掌握宏定义和宏替换的一般方法;掌握包含文件的处理方法;了解条件编译的作用和实现方法。语言程序设计教程第二版第十章预处理命令C10.1预处理命令简介

预处理命令:C源程序中以#开头、以换行符结尾的行

种类:宏定义#define、#undef

文件包含#include

条件编译#if、#ifdef、#else、#elif、#endif等其他

#line、#error、#program等本章主要讨论的内容!格式:“#”开头占单独书写行语句尾不加分号语言程序设计教程第二版第十章预处理命令C10.2宏定义

宏定义分为两种:不带参数的宏定义和带参数的宏定义。

1、不带参数的宏定义一般形式

#define标识符单词串指令名称宏名,被定义代表后面的单词串

宏体,是宏的内容文本

可缺省,表示宏名定义过或取消宏体功能

用指定标识符(宏名)代替字符序列(宏体)如#defineYES1#defineNO0#definePI3.1415926#defineOUTprintf(“Hello,World”);#defineSIZE10#defineINT_STR

"%d"voidmain()

{inta[SIZE],i;for(i=0;i<SIZE;i++)scanf(INT_STR,&a[i]);for(i=SIZE-1;i>=0;i--)printf(INT_STR,a[i]);}宏定义voidmain()

{inta[10],i;for(i=0;i<10;i++)scanf("%d",&a[i]);for(i=10-1;i>=0;i--)printf("%d",a[i]);}预编译处理后

注意:宏替换时仅仅是将源程序中与宏名相同的标识符替换成宏的内容文本,并不对宏的内容文本做任何处理。语言程序设计教程第二版第十章预处理命令C宏定义注意事项

C程序员通常用大写字母来定义宏名,以便与变量名区别。

如:#definePI3.14159宏定义的位置任意,但一般放在函数外面。

宏定义时,如果单词串太长,需要写多行,可以在行尾使用反斜线“\”续行符例如:#defineLONG_STRING"thisisaverylongstringthatis\usedasanexample"宏名的作用域是从#define定义之后直到该宏定义所在文件结束

#undef可终止宏名作用域#undef标识符#defineYES1voidmain(){……..}#undefYES#defineYES0voidmax(){……..}YES原作用域YES新作用域

宏定义可以嵌套定义,但不能递归定义

#defineR2.0#definePI3.14159#defineL2*PI*R(√)#defineSPI*R*R(√)#defineMM+10(×)程序中字符串常量即双引号中的字符,不作为宏进行宏替换操作

#defineXYZthisisatestprintf("XYZ");输出:XYZ,而不是:thisisatest。语言程序设计教程第二版第十章预处理命令C宏定义注意事项

宏定义一般以换行结束,不要用分号结束,以免引起不必要的错误#definePI3.14;

a=PI*2*2;

预编译处理后a=3.14;*2*2;

错误!宏可以被重复定义。

#defineN10

//第一次宏定义intf(){N的内容是10return(N*N);}#defineN20

//第二次宏定义voidmain(){N的内容是20printf("%d\n",N+f());}在定义宏时,如果宏是一个表达式,那么一定要将这个表达式用()括起来,否则可能会引起非预期的结果。

#defineNUM110#defineNUM220#defineNUMNUM1+NUM2voidmain()

{inta=2,b=3;a*=NUM;b=b*NUM;printf("a=%d,b=%d\n",a,b);}voidmain()

{inta=2,b=3;a*=10+20;b=b*10+20;printf("a=%d,b=%d\n",a,b);}预编译处理后输出结果:a=60,b=50

()()()输出结果:a=60,b=90

语言程序设计教程第二版第十章预处理命令C2、带参数的宏定义一般形式

#define标识符(参数列表)单词串参数表由一个或多个参数构成,参数只有参数名,没有数据类型符,参数之间用逗号隔开,参数名必须是合法的标识符通常会引用宏的参数

例:#defineS(a,b)a*b………..area=S(3,2);宏展开:area=3*2;宏展开:形参用实参换,其它字符保留宏体及各形参外一般应加括号()不能加空格例#defineS(r)PI*r*r相当于定义了不带参宏S,代表字符串“(r)PI*r*r”

例#definePOWER(x)x*xx=4;y=6;z=POWER(x+y);宏展开:z=x+y*x+y;一般写成:#definePOWER(x)((x)*(x))宏展开:z=((x+y)*(x+y));语言程序设计教程第二版第十章预处理命令C#defineMAX(x,y)(x)>(y)?(x):(y)…….voidmain(){inta,b,c,d,t;…….t=MAX(a+b,c+d);……}宏展开:t=(a+b)>(c+d)?(a+b):(c+d);intmax(intx,inty){return(x>y?x:y);}voidmain(){inta,b,c,d,t;…….t=max(a+b,c+d);………}【例】用宏定义和函数实现同样的功能语言程序设计教程第二版第十章预处理命令C带参的宏与函数区别带参宏函数处理时间编译时程序运行时参数类型无类型问题定义实参、形参类型处理过程不分配内存,简单的字符置换分配内存,先求实参值,再代入形参程序长度变长不变运行速度不占运行时间调用和返回占时间语言程序设计教程第二版第十章预处理命令C10.3文件包含处理过程功能一个源文件可将另一个源文件的内容全部包含进来一般形式#define<包含文件名>或#define“包含文件名”预编译时,用被包含文件的内容取代该预处理命令,再对“包含”后的文件作一个源文件编译<>:直接到系统指定的“文件包含目录”去查找被包含的文件“”:系统首先到当前目录下查找被包含文件,如果没找到,再到系统指定的“文件包含目录”去查找。

预编译处理后A源文件prg1.cpp#include"prg1.cpp"

B源文件prg2.cppBA新源文件prg2.cpp语言程序设计教程第二版第十章预处理命令C文件包含举例:#include"head.h"

#include"func.cpp"

voidmain(){inta,b,c;a=getnum();b=getnum();c=max(max(a,b),NUM);printf("MAX=%d\n",c);}(stdio.h文件中的内容)

#defineNUM10intmax(intx,inty){return(x>y?x:y);}intgetnum(){inta;scanf("%d",&a)return(a);}voidmain(){inta,b,c;a=getnum();b=getnum();c=max(max(a,b),NUM);printf("MAX=%d\n",c);}#include<stdio.h>#defineNUM10intmax(intx,inty){return(x>y?x:y);}intgetnum(){inta;scanf("%d",&a)return(a);}预编译处理后语言程序设计教程第二版第十章预处理命令C文件包含的优点:

一个大程序,通常分为多个模块,并由多个程序员分别编程。有了文件包含处理功能,就可以将多个模块共用的数据(如符号常量和数据结构)或函数,集中到一个单独的文件中(如上例中的文件head.h和func.cpp)。这样,凡是要使用其中数据或调用其中函数的程序员,只要使用文件包含处理功能,将所需文件包含进来即可,不必再重复定义它们,从而减少重复劳动。文件包含的几点说明

常用在文件头部的被包含文件,称为“标题文件”或“头部文件”,常以.h(head)作为后缀,简称头文件。在头文件中,除可包含宏定义外,还可包含外部变量定义、结构类型定义等。

一条包含命令,只能指定一个被包含文件。如果要包含n个文件,则要用n条包含命令。

文件包含可以嵌套,即被包含文件中又包含另一个文件。语言程序设计教程第二版第十章预处理命令C10.4条件编译根据一定的条件去编译源文件的不同部分,这就是条件编译。1、#if~#endif形式格式:#if条件1程序段1#elif条件2程序段2……#else程序段n#endif常量表达式。通常会用到宏名,条件可以不加括号“()”

#elif和#else可以没有

#endif必须存在,它是#if命令的结尾

如果条件1为真就编译程序段1,否则如果条件2为真就编译程序段2,…,如果各条件都不为真就编译程序段n。作用:

#if和#elif常常与defined命令配合使用,defined命令的格式为:

defined(宏名)或defined宏名功能:判断某个宏是否已经定义,如果已经定义,defined命令返回1,否则返回0。Defined命令只能与#if或#elif配合使用,不能单独使用。例如:#ifdefined(USA)的含义是“如果定义了宏USA”。

语言程序设计教程第二版第十章预处理命令C例:下面的程序利用ACTIVE_COUNTRY定义货币的名称

#defineUSA0#defineENGLAND1#defineFRANCE2#defineACTIVE_COUNTRYUSA

#ifACTIVE_COUNTRY==USA

char*currency=“dollar”;

//有效

#elifACTIVE_COUNTRY==ENGLANDchar*currency="pound"

;#elsechar*currency="france"

;#endifvoidmain(){floatprice1,price2,sumprice;scanf("%f%f",&price1,&price2);sumprice=price1+price2;printf("sum=%.2f%s",sumprice,currency);}char*currency=“dollar”;

voidmain(){floatprice1,price2,sumprice;scanf("%f%f",&price1,&price2);sumprice=price1+price2;printf("sum=%.2f%s",sumprice,currency);}预编译处理后语言程序设计教程第二版第十章预处理命令C2、#ifdef~#endif形式格式:#ifdef宏名程序段1#else程序段2#endif等价于“#ifdefined(宏名)”

在#ifdef和#else之间可以加多个#elif命令如果宏名已被#define行定义,则编译程序段1,否则编译程序段2

作用:#defineINTEGER#ifdefINTEGER

intadd(intx,inty)//有效

{return(x+y);}#elsefloatadd(floatx,floaty){return(x+y);}#endifvoidmain(){#ifdefINTEGER

inta,b,c;//有效

scanf("%d%d",a,b);printf("a+b=%d\n",add(a,b));#elsefloata,b,c;scanf("%f%f",a,b);printf("a+b=%f\n",add(a,b));#endif}intadd(intx,inty)//有效

{return(x+y);}voidmain(){inta,b,c;//有效

scanf("%d%d",a,b);printf("a+b=%d\n",add(a,b));}预编译处理后语言程序设计教程第二版第十章预处理命令C3、#ifndef~#endif形式格式:#ifndef宏名程序段1#else程序段2#endif如果宏名没被#define行定义,则编译程序段1,否则编译程序段2

作用:条件编译与分支语句二者之间的差别:条件编译是在预编译时处理;而条件语句则是在程序运行时处理。条件编译中的条件不可以包含变量名,只能是常量表达式(通常包含宏名),可以不加括号;而条件语句中的条件是条件表达式,可以包含变量或函数等,并且必须加括号。例如:#defineN10intNUM=10;#ifNUM==10…#endif

错误,NUM是变量。可改为:

#ifN==10

语言程序设计教程第二版第十章预处理命令C条件编译与分支语句二者之间的差别:条件编译是将满足编译条件的程序代码进行编译生成目标代码,不满足编译条件的程序代码将不进行编译;而分支语句则是不管满足条件的代码,还是不满足条件的代码,都要编译生成目标代码(包括分支语句本身),所以如果用条件语句来代替条件编译命令,程序的目标代码将变长

条件编译命令可以放在所有函数的外部,也可以放在某函数的内部;但分支语句只能出现在某函数内部。使用条件编译的源程序使用分支语句的源程序#include<stdio.h>#include<stdio.h>#defineNUM10#defineNUM10voidmain()voidmain(){{程序代码#ifNUM==10if(NUM==10)printf("NUMis10\n");printf("NUMis10\n");#elseelseprintf("NUMnotis10\n");printf("NUM

温馨提示

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

评论

0/150

提交评论