C语言 函数 预处理

上传人:206****923 文档编号:51502125 上传时间:2018-08-14 格式:PPT 页数:40 大小:79.50KB
返回 下载 相关 举报
C语言 函数 预处理_第1页
第1页 / 共40页
C语言 函数 预处理_第2页
第2页 / 共40页
C语言 函数 预处理_第3页
第3页 / 共40页
C语言 函数 预处理_第4页
第4页 / 共40页
C语言 函数 预处理_第5页
第5页 / 共40页
点击查看更多>>
资源描述

《C语言 函数 预处理》由会员分享,可在线阅读,更多相关《C语言 函数 预处理(40页珍藏版)》请在金锄头文库上搜索。

1、第6章 编译预处理n教学重点与难点:n1文件包含预处理命令n2宏定义语句的使用方法n3条件编译语句的使用方法n C语言与其他高级语言的重要区别是它具有编译 预处理功能,即由C语言编译预处理程序实现分析和 处理以 “#”开头的编译预处理命令。C语言的编译预 处理命令主要有宏定义、文件包含和条件编译。61 文件包含编译预处理 n定义:文件包含编译预处理,顾名思义,是指把一个指定的 文件包括到源文件中,然后再对源文件进行编译。n文件包含预处理语句的一般格式如下:n # include “文件名”n或 # include 文件名其中:文件名是磁盘中文本文件的名字。例如磁盘上存在着 两个文件:file1

2、.c和file2.c,在file2.c文件的开始有语句: #include “file1.c”,那么在对file2.c进行编译之前,系统会将 文件file1.c的内容包含进来代替此语句。n在使用文件包含编译预处理命令时需注意:n(1)一个# include命令只能指定一个被包含的文件,包含多个文件时需 要使用多个文件包含命令。n(2)文件包含可以嵌套。例如:文件1中包含文件2,文件2中包含文件3 ,此时只须保证文件2在文件3之前处理即可。n(3)包含命令中的被包含文件的文件名可以用双引号或尖括号括起来。 二者的区别是:用双引号时,系统首先在源文件所在的目录中查找要包 含的文件,若找不到,再到系

3、统设定的目录中查找。若在双引号中指明 文件路径,系统就到指定目录中查找被包含文件;当使用尖括号包围包 括文件时,其意义是指示编译系统仅在系统设定的标准目录中搜索包括 文件。n(4)被包含文件与源文件在编译处理后已经成为一个文件,因此,如果 被包括的文件中有全局变量(包括静态全局变量),则它也在包含文件 中有效,不必再用extern说明。n例6-1 文件包含预处理语句的使用nmymath.h的内容如下:n # define ADD(x,y) (x+y)n # define MUL(x,y) (x)*(y)n # define PI 3.1415926n # define G 2.718n tes

4、t.c内容如下:n# include “mymath.h”nmain ( )nnint a=6,b=9;nprintf(“a+b=%dn”,ADD(a,b);nprintf(“a*b=%dn”,MUL(a,b);n62 宏定义n宏定义是一种很重要的编译预处理命令,由 #define命令实现,根据实际应用的需要可以分为 如下两种形式:n带参数的宏定义、不带参数的宏定义n1不带参数的宏定义n不带参数的宏定义命令我们在前面已介绍过,它的一般形式 为:n#define 标识符 字符串n其中:n(1)“标识符”是宏名,其作用是用指定的宏名来代替一个指 定的字符串,为了与变量名区分一般用大写字母。在编译时

5、程 序中所有出现“宏名”的地方,都用该字符串的内容进行替换 ,此过程称为“宏展开”。n(2)宏定义减少了字符串的书写工作量,易于修改,提高了 程序的可移植性。n(3)宏定义末不用分号,否则会将分号当作字符串 的一部分一起赋给标识符。n(4)宏名的有效范围为定义命令之后到本源文件的 结束或遇到#undef 宏名终止该宏定义。n(5)可以用# undef命令终止宏定义的作用域。n例如: #define PI 3.1415926n main ( )n n PI的作用域n n # undef PIn f ( ) n n在函数f ( )中不能再使用PI。n(6)宏定义可以嵌套,后面定义的宏可以引用前 面

6、已定义的宏,层层置换。n 例如:n #define r 3.0n #define PI 3.1415926n #define c 2.0*PI*rn #define s PI*r*rn #define v 4.0/3.0*PI*r*r*rn(7)如果双引号括起来的字符串内存在与宏 名相同的字符也不置换,仅作为字符串的一 部分。n(8)宏定义是用于预处理命令的一个专用名 词,与定义变量不同,只作字符替换,不分 配内存。n例6-2 不带参数的宏定义n #define PI 3.1415926nmain ( )nnfloat c,s,r,v;nprintf(“input radius:”);nsca

7、nf (“%f”,nc=2.0*PI*r;ns=PI*r*r;nv=4.0/3.0*PI*r*r*r;nprintf (“c=%10.4fns=%10.4fnv=%10.4fn”,c,s,v);nn运行结果:ninput radius:3回车nc=18.8496ns=28.2743nv=113.0973n2带参数的宏定义n 带参数的宏定义不仅作简单的字符替换,还要进行参数替 换。带参数宏定义的一般格式如下:n# define 宏名(参数表) 字符串n例如:n #define s(a,b) (a+b)*2.0n c=s (4,5); n说明:n(1)置换顺序: s (a,b) (a+b)*2.0

8、n n c=s(4,5) (4+5)*2.0n(2)宏定义时,宏名与参数的圆括号之间不能有 空格,否则将空格后的字符都作为替代字符串的 一部分,这样带参数的宏定义就变成了不带参数 的宏定义了。n(3)带参数宏定义的展开只是将语句中的宏名后 面括号内的实参字符代替#define命令行中的形参 。n例如:#define PI 3.1415926n #define s(r) PI*r*r n area=s(a);n实参a代替形参r ,得到:area=s(a)=PI*a*a。n(4)实参可以为表达式,但这时要注意保证实参 和形参的一致性。n例:本例我们将实参a改成a+b,即area=s(a)改成 ar

9、ea=s(a+b),我们想要的结果area=PI*(a+b)*(a+b), 但实际上我们得到是area=PI*a+b*a+b,为了要得我 们想要的结果应该在定义时将形参用一个圆括号括 起来,即:n #define s(r) PI*(r)*(r) n这样才能保证无论实参是什么样的表达式,都能得 到正确的结果。n n例6-3 带参数的宏定义n #define POWER(x) (x)*(x)n main()n n int y;n scanf(“%d”,n printf(“y=%d, y*y=%dn”,y, POWER(y);n n n 从上述例题中可以看出,带参数的宏定义与函 数的使用非常相似,但

10、二者是不同的。两者的区别 有如下几点:n(1)函数调用时先求出实参的值,然后代入形参。 而带参数的宏定义只是进行简单的字符替换。n(2)函数调用是在程序运行时处理的,并分配临时 的内存单元。而宏展开则是在编译预处理时进行的 ,在展开时并不分配内存单元,不进行值的传递, 也没有“返回值”。n(3)对函数中的实参和形参都要定义类型,并且要 求形参和实参类型一致。而宏定义不存在类型问题, 宏名字无类型,其参数也无类型,仅是一个符号代表 ,展开时代入指定的字符串即可,宏定义时字符串可 以是任意类型的数据。n(4)函数调用只能得到一个返回值,而用宏可以设 法得到几个值。 n例6-4 利用宏定义可以得到多

11、个值。n#define PI 3.1415926n#define CIRCLE (R,C,S,V) C=2*PI*R;S=PI*R*R;V=4.0/3.0*PI*R*R*R nmain ( )nnfloat r, c,s,v;nscanf (“%f”,nCIRCLE (r,c,s,v);nprintf (“r=%6.2f,c=%6.2f,s=%6.2f,v=%6.2fn”,r,c,s,v);n n经编译预处理将宏定义展开后程序如下:nmain ( )nnfloat r, c,s,v;nscanf (“%f”,n c=2*3.1415926*r;s=3.1415926*r*r;v=4.0/3.0

12、*3.1415926*r*r*r ;nprintf (“r=%6.2f,c=%6.2f,s=%6.2f,v=%6.2fn”,r,c,s,v);nn运行情况如下:n3.5回车nr=3.50,c=21.99,s=38.48,v=179.59n(5)使用宏次数多时,宏展开后源程序长,因为每 展开一次都使程序增长;而函数调用不使程序变长 。n(6)宏替换不占用运行时间,而函数调用则占用运 行时间(分配内存单元、保护现场、值传递、执行 函数、返回函数值等)。63 条件编译n 在很多情况下,为了增强程序的可移植 性,C语言源程序中包含了各种版本的程序段 ,但在某种情况下,只希望对一部分内容进 行编译,即为

13、其指定编译的条件,此时称为 条件编译。n条件编译需要条件编译命令,条件编译的命令主要 有如下3种:n1 # if 条件1n 源程序段1n # elif 条件2n 源程序段2n # else n 源程序段3n # endifn作用:当所指定的条件1为真时,在程序编译 阶段只编译程序段1,否则如果条件2为真, 则在程序编译阶段只编译程序段2。如果条件 1和条件2都为假,则在程序编译阶段只编译 程序段3。n其中:n(1)elif是else if的缩写,#elif和#else都可以没有 ,#elif也可以有多个。但#endif必须有,它是#if命 令的结尾。n(2)条件必须是一个常量表达式,通常会用到

14、宏名 。当某条件成立时,此条件下面的源程序有效,否 则无效。条件不能用括号括起来。n(3)每个命令都独占一行。n例6-5 条件编译应用一。n# define a 1main ( )n# if a0nprintf (“a是正数”);n# elif a=0 nprintf (“a是零”);n# else nprintf (“a是负数”);nn编译器预处理后的源程序为:nmain ( )nnprintf (“a是正数”);nn2 # ifndef 宏名n 源程序段1n # elsen 源程序段2n # endifn作用:表示如果宏名未被定义过则编译程序段1,否 则编译程序段2。n3 #ifdef 宏名1n 源程序段1n #elif define 宏名2n 源程序段2n #elsen 源程序段3n #endifn作用:当指定的宏名已被定义则编译程序段1,否则 编译程序段2。n例6-7 条件编译应用二。n #define intn void main ( )n n#ifdef intn int a; 有效n scanf(“%d”,n .n#elsenchar c;nscanf(“%c”,n n#endifnn编译器预处理后的源程序如下:nvoid main ( )n nint a;nscanf(“%d”,n64 本章小结n 预处理命令可以减少程序的工作量,提高程序 的可

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 行业资料 > 其它行业文档

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号