C语言程序设计课件.ppt_第1页
C语言程序设计课件.ppt_第2页
C语言程序设计课件.ppt_第3页
C语言程序设计课件.ppt_第4页
C语言程序设计课件.ppt_第5页
已阅读5页,还剩29页未读 继续免费阅读

下载本文档

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

文档简介

第九章 编译预处理,9.1宏定义 9.2文件包含处理 9.3条件编译 9.4 带参数的主函数,概 述,在前面各单元中我们已经使用了部分以“#”符号开头的命令。例如,# define、# include等。这些命令是在源程序正式编译前进行处理的,称为“编译预处理”命令。编译预处理主要包括宏的处理、包含文件的处理、条件编译的处理等。,宏定义,1、不带参数的宏定义,用一个指定的标识符(即名字)来代表一个字符串 它的一般形式为 define 标识符 字符串 这就是已经介绍过的定义符号常量。如: define PI 3.1415926,#define PI 3.1415926 main() float l,s,r,v; printf(“input radius:”); scanf(“%f”, ,例1:下面的程序使用了宏定义,给出其运行结果,3、说明:,(1)宏名一般习惯用大写字母表示,以便与变量名相区别。,(2)使用宏名代替一个字符串,可以减少程序中重复书写某 些字符串的工作量。,(3)宏定义是用宏名代替一个字符串,也就是作简单的置换, 不作正确性检查。,define PI 3.1415926; areaPI* r* r; 经过宏展开后,该语句为 area 3.1415926;* r* r ; 显然出现语法错误。,(5)define命令出现在程序中函数的外面,宏名的有效范围 为定义命令之后到本源文件结束。通常, define命令写 在文件开头,函数之前,作为文件一部分,在此文件范围 内有效。,(6)可以用undef命令终止宏定义的作用城。例如:,# define G 9.8 main() . . . # undef G f1() . . . ,G的有效范围,(7)在进行宏定义时,可以引用已定义的宏名,可以层层 置换。,#define R 3.0 #define PI 3.1415926 #define L 2*PI*R #define S PI*R*R main() printf(“L=%fnS=%fn”,L,S); ,例2 分析下面程序的运行结果,运行情况如下: L=18.849556 S=28.274333,(8)对程序中用双括号括起来的字符串内的字符,即使与宏 名相同,也不进行置换。,(9)宏定义是专门用于预处理命令的一个专用名词,它与定 义变量的含义不同,只作字符替换,不分配内存空间。,4、带参数的宏定义,带参数的宏定义除了字符串替换之外,还要进行参数的替换。 定义的一般形式为 define 宏名(参数表) 字符串 字符串中包含在括弧中所指定的参数。如: define S(a,b) a *b area=S(3,2);,例3:分析下面程序的运行结果,#define PI 3.1415926 #define S(r) PI*r*r main() float a,area; a=3.6; area=S(a); printf(“r=%fnarea=%fn”,a,area); ,运行结果如下: r=3.600000 area=40.715038 赋值语句area=S(a);经宏展开后为 area=3.1415926*a*a,5、说明:,(1)对带参数的宏的展开只是将语句中的宏名后面括号内的 实参字符串代替 define命令行中的形参。,(2)在宏定义时,在宏名与带参数的括弧之间不应加空格, 否则将空格以后的字符都作为替代字符串的一部分。,例如,如果有 define S (r) PI*r*r 被认为 S是符号常量(不带参的宏名),它代表字符串“(r) PI r r”。 如果在语句中有 area=S (a); 则被展开为 area=(r) PI*r*r (a) 显然不对了。,(3)带参的宏定义与函数是不同的。主要有:, 函数调用时,先求出实参表达式的值,然后带入形参。 而使用带参的宏只是进行简单的字符替换。, 函数调用是在程序运行时处理的,分配临时的内存单元。 而宏展开则是在编译时进行的,在展开时并不分配内存单 元,不进行值的传递处理,也没有“返回值”的概念。, 对函数中的实参和形参都要定义类型,二者的类型要求一 致,如不一致,应进行类型转换。而宏不存在类型问题, 宏名无类型,它的参数也无类型,只是一个符号代表,展 开时代入指定的字符即可。宏定义时,字符串可以是任何 类型的数据。例如: define CHAR1 CHINA(字符) define a 3.6 (数值), 调用函数只可得到一个返回值,而用宏可以设法得到几 个结果。, 使用宏次数多时,宏展开后源程序长,因为每展开一次都 使程序增长,而函数调用不使源程序变长。, 宏替换不占运行时间,只占编译时间。而函数调用则占运 行时间(分配单元、保留现场、值传递、返回)。 一般用宏来代表简短的表达式比较合适。有些问题,用宏 和函数都可以。如:,define MAX(x,y) (x)(y)? (x):(y) main() int a,b,c,d,t; t= MAX(a+b,c+d); , , ,赋值语句展开后为 t(ab)(cd)? (ab):(cd); 注意:MAX不是函数,这里只有一个宏,在main函数中就能 求出t的值。这个问题也可用函数来求:,int max(int x,int y) return(xy?x:y); main() int a,b,c,d,t; t= max(a+b,c+d); , , ,max是函数,在main函数中调用max函数才能求出t的值。,#define PR printf #define NL n” #define D ”%d #define E %d #define D1 D NL #define D2 D E NL #define D3 D E E NL #define D4 D E E E NL #define S “%s” main() int a,b,c,d; char string=“CHINA”; a=1,b=2,c=3,d=4; PR(D1,a); PR(D2,a,b); PR(D3,a,b,c); PR(D4,a,b,c,d); PR(S,string); ,例4:分析下面程序的运行结果:,运行时输出以下结果: 1 12 123 1234 CHINA,文件包含命令可以将另一个C源程序的全部内容包含进来,它可以避免不必要的重复劳动。,文件包含处理,1、一般形式:,include “文件名” 或 include ,2、例:可以将例4程序改为:,(1)文件 format.h #define PR printf #define NL n” #define D “%d #define E %d #define D1 D NL #define D2 D E NL #define D3 D E E NL #define D4 D E E E NL #define S “%s”,(2)文件file1.c #include “format.h” main() int a,b,c,d; char string=“CHINA”; a=1,b=2,c=3,d=4; PR(D1,a); PR(D2,a,b); PR(D3,a,b,c); PR(D4,a,b,c,d); PR(S,string); ,3、说明,(1)一个include命令只能指定一个被包含文件,如果要包含 n个文件,要用n个include命令。,(2)如果文件1包含文件2,而文件2中要用到文件3的内容,则 可在文件1中用两个include命令分别包含文件 2和文件3, 而且文件3应出现在文件2之前,即在 filel.c中定义: include “file3.h” include “file2.h”,(3)在一个被包含文件中又可以包含另一个被包含文件,即文 件包含是可以嵌套的。,(4)在include命令中,文件名可以用双引号或尖括号括起来。二者的区别是 用尖括号(即file2.h形式)时,系统到存放C库函数头文件所在的目录中寻找要包含的文件,这称为标准方式。 用双引号(即“file2.h”形式)时,系统先在用户当前目录中寻找要包含的文件,若找不到,再按标准方式查找(即再按尖括号的方式查找)。,(5)被包含文件(file2.h)与其所在的文件(即用 include 命令的原文件filel.c),在预编译后已成为同一个文件 (而不是两个文件)。,条件编译,一般情况下,源程序中所有的行都参加编译。但是有时 希望对其中一部分内容只在满足一定条件才进行编译,也就 是对一部分内容指定编译的条件,这就是“条件编译”。,条件编译命令有以下几种形式: (1)ifdef 标识符 程序段1 else 程序段2 endif,它的作用是当所指定的标识符已经被 define命令定义 过,则在程序编译阶段只编译程序段1,否则编译程序段2。 其中else部分可以没有,即 ifdef 标识符 程序段1 endif,(2)ifndef 标识符 程序段 1 else 程序段 2 endif,它的作用是若标识符未被定义过则 编译程序段1, 否则 编译程序段2。,(3) if 表达式 程序段1 else 程序段2 endif,它的作用是当指定的表达式值为真(非零)时就编译程 序段1,否则编译程序段2。,例 输入一行字母字符,根据需要设置条件编译,使之能将字母 全改为大写输出,或改为小写字母输出。,程序如下:,define LETTER 1 main() char str20=“c language”,c; int i; i=0; while(c=stri)!=0) i+; #if LETTER if (c=a ,运行结果为: C LANGUAGE,条件编译,带参数的主函数,一般情况下,在DOS环境执行文件的形式为“c:命令动词 参数表”。其中参数表被称为命令行参数。,其中,argc表示命令行参数的个数,指针数组argv分别指向命令行各参数的首地址。,在编辑C语言源程序时,main()函数可带有两个形参,形式为: void main(int argc,char *argv),例如: 取名file.c的文件经过编译、连接后产生file.exe,在DOS提示符下输入如下字符串时: c:file parameter1 parameter2 则程序运行时,系统自动将命令行参数的个数3赋给argc。,其中, argv0指向字符串“file”的首地址; argv1指向字符串“parameter1”的首地址; argv2指向字符串“parameter2”的首地址。 如果文件名前有路径,它们都保存在argv0中。,例:如下带参数的主函数 #include “stdio.h“ void main(int argc,char *argv) int i; for(i=1;iargc;i+) printf(“%sn“,argvi); ,通过编译生成file可执行文件后,在DOS的提示符下输入file hello world,则程序输出为: hello world,1、给出下面程序宏替换后的结果。 #define PI 3.1415926 #define R 3.0 #define L 2*PI*R #define S PI*R*R main() printf(“l=%f ns=%fn“,L,S); ,课堂练习,答案: 第一次替换:printf(“l=%f ns=%fn“, 2*PI*R, PI*R*R); 第二次替换:printf(“l=%f ns=%fn“, 2*3.1415926*3.0, 3.1415926*3.0*3.0);,分析:学习宏替换要注意以下几点: 宏名一般习惯用大写字母,以便与变量名相区别; 宏替换由编译程序预先进行;宏名用作代替一个字符串,不作语法检查; 宏替换范围是除用双引号引起来的字符串以外的所有宏名字。 (4) 若替换后文本串中仍含有宏名字,将再次进行替换,直到程序中不含宏名字为止。 (5) 宏定义不是语句,所以不能在行尾加分号。否则,宏展开时,会将分号作为字符串的1个字符,用于替换宏名。 C语言允许宏定义出现在程序中函数外面的任何位置,但一般情况下它总写在文件的开头。,2给出下面程序宏替换后的结果。 #define PF(x) x*x /*#define PF(x) (x)*(x) */ /*#define PF(x) (x)*(x) */ main() int a=2, b=3, c; c=PF(a+b)/PF(a+1); printf(“nc=%d “,c); ,答案: (1)按第一种宏定义: c=a+b*a+b/a+1*a+1; (2)按第二种宏定义: c=(a+b)*(a+b)/(a+1)*(a+1); (3)按第三种宏定义:c=(a+b)*(a+b)/(a+1)*(a+1);,分析: (1)定义有参宏时,宏名与左圆括号之

温馨提示

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

评论

0/150

提交评论