《预处理定义》PPT课件.ppt_第1页
《预处理定义》PPT课件.ppt_第2页
《预处理定义》PPT课件.ppt_第3页
《预处理定义》PPT课件.ppt_第4页
《预处理定义》PPT课件.ppt_第5页
已阅读5页,还剩23页未读 继续免费阅读

下载本文档

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

文档简介

,第九章,预处理命令,本章要点,宏定义 文件包含 条件编译,主要内容,9.1 宏定义 9.2 “文件包含”处理 9.3 条件编译,(4)经过预处理后的程序不再包括预处理命令了,最后再由编译程序对预处理后的源程序进行通常的编译处理,得到可供执行的目标代码。 (5)为了与一般C语句相区别,预处理命令以符号“#”开头。,预处理命令的特点,(1)用于改进程序设计环境,提高编程效率。 (2)它不是C语言本身的组成部分,不能直接对它们进行编译(因为编译不能识别它们)。 (3)必须在对程序进行通常的编译(包括词法和语法分析、代码生成、优化等)之前,先对程序中这些特殊的命令进行“预处理”,即根据预处理命令对程序作相应的处理。,如:程序中用#define命令定义了一个符号常量A,则在预处理时将程序中所有的A都置换为指定的字符串。 程序中用#include命令包含一个文件“stdio.h”,则在预处理时将stdio.h文件中的实际内容代替该命令。,9.1 宏定义(1), 不带参数的宏定义 用一个指定的标识符(即名字)来代表一个字符串。其一般形式为,#define 标识符 字符串,宏定义使用户能以一个简单的名字代替一个长的字符串。 这个标识符成为“宏名”。 在预编译时将宏名替换成字符串的过程称为“宏展开”。#define是宏定义命令,9.1 宏定义(2),#include #define PI 3.1415926 void main() float l,s,r,v; printf(“input radius:”); scanf(“%f”, ,input radius:4 l=25.1327 s=50.2655 v=268.0826,9.1 宏定义(3),宏名一般习惯用大写字母表示,以便与变量名区别,但这并非规定,也可用小写字母。 使用宏名代替一个字符串,可以减少程序中重复书写某些字符串的工作量,同时也避免书写字符串出错。另外,可以通过改变#define命令行来更改宏名所代表的字符串。 宏定义是用宏名代替一个字符串,也就是作简单的置换,不作正确性检查,即预编译时不作任何语法检查。 宏定义不是C语句,不必在行末加分号,如果加了分号则连分号一起进行置换。 #define命令出现在程序函数的外面,宏名的有效范围为定义命令之后到本源文件结束。,如:定义数组大小,可以用 #define array_size 1000 int arrayarray_size; 当该程序在另外一个场合中,需要定义更长的数组,则只要更改#define命令行即可实现,即改为 #define array_size 2000 在该场合下array_size所代表的是2000,使用宏定义,可以提高程序的通用性。,一个宏定义如下: #define PI 3.141s9 在宏替代时,不会指出该宏是错误的,只有在编译的时候,才会提示在使用宏的行存在语法错误。,9.1 宏定义(4),可以用#undef命令终止宏定义的作用域。 在进行宏定义时,可以引用已定义的宏名,可以层层置换。 对程序中用双撇号括起来的字符串内的字符,即使与宏名相同,也不进行置换。 宏定义是专门用于预处理命令的一个专用名词,它与定义变量的含义不同,只作字符替换,不分配内存空间。,9.1 宏定义(5),带参数的宏定义 带参数的宏定义不是进行简单的字符串替换,还要进行参数替换。其一般形式为,#define 宏名(参数表) 字符串,字符串中包含在括号中所指定的参数。,对带参数的宏定义是这样展开置换的:在程序中如果有带实参的宏,则按#define命令行中指定的字符串从左到右进行置换。如果串中包含宏中的形参,则将程序语句中相应的实参(可以是常量、变量或表达式)代替形参。如果宏定义中的字符串中的字符不是参数字符,则保留。,定义一个a和b为边的矩形面积的宏: #define S(a,b) a*b area=S(3,2); 展开后为: area=3*2;,9.1 宏定义(6),#include #define PI 3.1415926 #define S(r) PI*r*r void main() float a,area; a=3.6; area=S(a); printf(“r=%fnarea=%fn”,a,area); ,9.1 宏定义(7),说明: 对带参数的宏的展开只是将语句中的宏名后面括号内的实参字符串代替#define命令行中的形参。当实参是一个表达式(非单个常量或变量),则在宏定义时,最后宏所代表的字符串内把宏中的形参用括号括起来,以免在宏展开时,造成计算错误。 在宏定义时,在宏名与带参数的括号之间不应加空格;否则将空格以后的字符都作为代替字符串的一部分。,如:当如下语句出现时 area=S(a+b); 展开为: area=3.1415926*a+b*a+b; 为实现原意,宏定义应改为 #define S(r) PI *(r) *(r),如下宏定义: #define S (r) PI*r*r 对于语句 area=S(a); 将展开为: area=(r) PI*r*r(a);,9.1 宏定义(8),带参数的宏和函数之间,混淆:在调用函数时也是在函数名后的括号内写实参,也要求实参和形参的数目相等。,不同之处: 函数调用时,先求出实参表达式的值,然后代入形参;而使用带参数的宏只是进行简单的字符替换。 函数调用是在程序运行时处理的,为形参分配临时的内存单元;而红展开则是在编译前进行的,在展开时不分配内存单元,不进行值的传递处理,也没有“返回值”的概念。,9.1 宏定义(9),对函数中的实参和形参都要定义类型,二者的类型要求一致,如不一致,应进行类型转换;而宏不存在类型问题,宏名无类型,它的形参也无类型,只是一个符号代表,展开时代入指定的字符串即可。宏定义时,字符串可以时任何类型的数据。 调用函数只可得到一个返回值;而用宏可以设置得到几个结果。,#define PI 3.1415926 #define CIRCLE(R,L,S,V) L=2*PI*R;S=PI*R*R;V=4.0/3.0*PI*R*R*R;,9.1 宏定义(10),使用宏次数多时,宏展开后源程序变长,因为每展开一次都使程序增长;而函数调用不会使源程序变长。 宏替换不占运行时间,只占编译时间;而函数调用则占运行时间(分配单元、保留现场、值传递、返回)。,一般用宏来代表简短的表达式比较合适。有些问题,用宏和函数都可以,但用宏可以简化程序。 如:宏定义 #define MAX(x,y) (x)(y)?(x):(y) 函数: int max(int x,int y) return(xy?x:y);,9.1 宏定义(11),用宏代表输出格式 #include #define PR printf #define NL “n” #define D “%d” #define D1 D NL #define D2 D D NL #define D3 D D D NL #define D4 D D D D NL #define S “%s”,void 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); ,1 12 123 1234 CHINA,9.2 “文件包含”处理(1),所谓“文件包含”处理是指一个源文件可以将另外一个源文件的全部内容包含进来,即将另外的文件包含到本文件之中。C语言提供了#include命令用来实现“文件包含”的操作。 其一般形式为,#include “文件名” 或 #include ,9.2 “文件包含”处理(2),好处:“文件包含”命令可以节省程序设计人员的重复劳动。 如:某单位的人员往往使用一组固定的符号常量(g=9.81, pi=3.1415926,e=2.718,c=),可以把这些宏定义命令组成一个头文件,然后各人都可以用#include命令将这些符号常量包含到自己所写的源文件中。这样每个人就可以不必重复定义这些符号常量,相当于工业上的标准零件,拿来就用。,将宏代表输出格式做出头文件,并包含到用户程序中: (1)将格式宏做成头文件format.h #include #define PR printf #define NL “n” #define D “%d” #define D1 D NL #define D2 D D NL #define D3 D D D NL #define D4 D D D D NL #define S “%s”,(2)主文件file1.c void 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); ,9.2 “文件包含”处理(3),注意:“文件包含”是预处理操作,它在编译前将包含的文件包含到主文件中,得到一个新的源程序,然后对这个文件进行编译,得到一个目标文件(.obj)。 常用在文件头部的被包含的文件称为“标题文件”或“头文件”,常以“.h”为后缀。当然也可不用“.h”为后缀,而用“.c”为后缀或者没有后缀也是可以的,但用“.h”作后缀更能表示此文件的性质。 如需要修改程序中常用的一些参数,可以不必修改每个程序,只需把这些参数放在一个头文件中,在需要时修改头文件即可。但是应当注意,被包含文件修改后,凡包含此文件的所有文件都要全部重新编译。 头文件除了可以包含函数原型和宏定义外,还可以包括结构体类型定义和全局变量定义等。,9.2 “文件包含”处理(4),说明:,一个#include命令只能指定一个被包含文件,如果要包含n个文件,要用n个#include命令。 如果文件1包含文件2,而在文件2中要用到文件3的内容,则会在文件1中用两个#include命令分别包含文件2和文件3,而且文件3应出现在文件2之前。 在一个被包含文件中又可以包含另一个被包含文件,即文件包含是可以嵌套。 在#include命令中,文件名可以用双撇号或尖括号括起来。,二者区别: 用尖括号时,系统到存放C库函数头文件的目录中寻找要包含的文件,这称为标准方式。 用双撇号时,系统先在用户当前目录中寻找要包含的文件,若找不到,再按标准方式查找。 一般来说,如果为调用库函数则用#include命令来包含相关的头文件,则用尖括号,以节省查找时间;如果要包含的是用户自己编写的文件,一般用双撇号。 若文件不在当前目录中,在双撇号内应给出文件路径。,9.2 “文件包含”处理(5),被包含文件与其所在的文件,在预编译后已成为同一个文件,因此如果被包含文件中有全局静态变量,它在包含该文件的文件中也是有效的,不必用extern声明。,9.3 条件编译(1),一般情况下,源程序中所有行都参加编译。但是有时希望程序中一部分内容只在满足一定条件时才进行编译,也就是对这一部分内容指定编译的条件,称为“条件编译”。 有时,希望在满足某条件时对某一组语句进行编译,而当条件不满足时则编译另一组语句。 条件编译命令可以处于程序的任何地方。,9.3 条件编译(2),条件编译命令有以下几种形式:, #ifdef 标识符 程序段1 #else 程序段2 #endif,说明:它的作用是若指定的标识符已经被#define命令定义过,则在程序编译阶段编译程序段1;否则编译程序段2。其中#else部分可以没有,即 #ifdef 标识符 程序段 #endif,程序段可以是语句组,也可以是命令行,9.3 条件编译(3),好处:条件编译对于提高C源程序的通用性是很有好处的,若一个C源程序在不同计算机系统上运行,而不同的计算机又有一定的差异,往往需要对源程序作必要的修改,这就降低了程序的通用性。通过条件编译命令可以提高程序的通用性。,#ifdef COMPUTER_A #define INTEGER_SIZE 16 #else #define INTEGER_SIZE 32 #endif,说明:如果COMPUTER_A已定义,则假定目前程序在整数为16位的计算机上运行,若未定义,则认为不在整数为16位的计算机上运行,而是32位的计算机上运行。,此前,可以用命令行#define来定义COMPUTER_A,其后可有任意字符串,也可无字符串,如 #define COMPUTER_A 0 #define COMPUTER_A,9.3 条件编译(4),在调试程序时,常常希望输出一些所需的信息,而在调试完成后不再输出这些信息。可以在源程序中插入以下的条件编译段: #ifdef DEBUG printf(“x=%d,y=%d,z=%dn”,x,y,z); #endif 如果在它的前面有以下命令行: #define DEBUG,9.3 条件编译(5), #ifndef 标识符 程序段1 #else 程序段2 #endif,与相反。,9.3 条件编译(6), #if 表达式 程序段1 #else 程序段2 #endif,它的作用是当指定的表达式值为真时就编译程序段1;否则编译程序段2。可以事先给定条件,使程序在不同的条件下执行不同的功能。,9.3 条件编译(7),输入一行字母字符,根据需要设置条件编译,使之能将字母全改为大写输出,或全改为小写字母输出。,#include #define LETTER 1 void main() char str20=“C Language”,c; int i; while (c=s

温馨提示

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

评论

0/150

提交评论