页数:30页文件大小:219.4 KB来源: C语言程序设计ppt课件
本课件先说明编译预处理在编译流程中的位置与作用,随后讲解不带参数宏的定义形式、作用域与宏展开规则,带参数宏的展开与易错之处;接着介绍文件包含的两种查找形式,最后给出条件编译的几种形式及其在程序移植与调试中的应用。
第5章 编译预处理
教学内容1.了解预编译的概念,2.掌握宏定义的方法(主要是无参)。
3.了解“文件包含”与预处理的应用。
4.了解条件编译的几种形式。
教学要求5.1概述5.2宏定义5.3文件包含5.4条件编译结束5.5小结
什么是编译预处理编译预处理是指
在进行编译之前,先对源程序中的编译预处理命令进行处理;然后再将处理的结果,和源程序一起进行编译,以得到目标代码。5.1概述
#include不带参数宏定义
功能:用指定标识符(宏名)代替字符序列(宏体)如:#defineYES1#defineNO0#definePI3.1415926#defineOUT
printf("Hello,World");作用域
从定义命令到文件结束;可终止作用域,格式:#undef宏名例:#defineYES1
main(){ …… } #undefYES……#defineYES0max(){ …… } 5.2宏定义YES新作用域YES原作用域宏展开
预编译时,用宏体替换宏名如:#defineYES1#defineNO0……if(x==YES)
printf("correct!"); elseif(x==NO)printf("error!");printf("2*P=%f",2*P); 5.2宏定义展开后:if(x==1)printf("correct!"); elseif(x==0)printf("error!"); 不作语法检查宏展开:printf("2*P=%f",2*3.1);宏定义不能递归如
宏定义中使用必要的括号“()”如:上例宏展开:(若是求长方形周长就错了)var=80+40*2;5.2宏定义(WIDTH+40)(80 + 40)
例1*给出下面宏替换的结果
#defineR5.0#defineFORMAT"Area=%f\n"#definePI3.14#defineAREAR*R*PI#definePRprintf
main(){ PR(FORMAT,AREA); PR("FORMAT"); } 5.2宏定义运行结果:Area =78.500000FORMATmain()//宏替换的结果{ printf("Area=%f\n",5.0*5.0*3.14); printf("FORMAT"); }带参数宏定义转下一部分
宏体及各形参外一般应加括号()例
#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));
例2*用带参数宏定义求两个数的最大值
#include<stdio.h>main(){ inta,b,c; floatx,y,z; scanf("%d%d",&a,&b); c=MAX(a,b); scanf("%f%f",&x,&y); z=MAX(x,y); printf("c=%dz=%f\n",c,z); } 5.2宏定义宏展开c = (a)>(b)?(a):(b)宏展开z = (x)>(y)?(x):(y)运行结果:3带参的宏与函数区别
2宏定义函数带参宏区别程序运行时编译时处理时间定义实参,形参类型无类型问题参数类型分配内存先求实参值,再代入形参不分配内存简单的字符置换处理过程不变变长程序长度调用和返回占时间不占运行时间运行速度
在定义和使用宏调用时应注意的问题
运算符优先级引起的问题
宏定义中的字符串相连顺序书写
的两个字符串间仅由空格、换行符或制表符分隔,编译时,自动将这两个串连接。如:#defines1"123"#defines2"ABC"# definess1
s2//连接s1和s2,s为"123ABC"4.符号常量(重点掌握)在定义无参宏时,若“语言符号字符串”是一个常量,则相应的“宏名”就是一个符号常量。
如:#defineEOF-1//文件尾#defineNULL0//空指针
使用宏定义的优点
概念用
#include开始的预处理命令称文件包含命令。文件包含是指,一个源文件可以将另一个源文件的全部内容包含进来。二、一般格式#include<文件名>或#include"文件名"预处理过程按规定方法寻找文件
若找到,用被包含文件的内容取代该预处理命令,再对“包含”后的文件作一个源文件编译;
若找不到,则预编译出错,提示无法打开相应文件。
5.3文件包含file2.cfile1.c
#include"file2.c"A取代BB文件包含的优点
有了文件包含处理功能,就可以将多个模块共用的数据(如符号常量和数据结构)或函数,集中到一个单独的文件中。
这样,凡是要使用其中数据或调用其中函数的人,只要使用文件包含,将所需文件包含进来即可,不必再重复定义它们,从而减少重复劳动。
5.3 文件包含
一条包含命令,只能指定一个被包含文件。如果要包含n个文件,则要用n条包含命令。5.3文件包含file2.cfile1.c
#include命令行应写在程序的开头。#include"file2.c"#include"file3.c"A取代BBfile3.c取代CC文件包含可以嵌套
#include"file3.c"Bfile3.cCCfile1.c#include"file2.c"ACBfile2.c#include"file3.c"B取代取代前面例子中
头文件主要内容是标准库函数的原型说明、一些系统使用的符号常量(如EOF、NULL)定义等。
#include命令包含的是系统标准库的各种头文件(如stdio.h、math.h):#include命令将这种文件包含进程序,相当于在源程序的前面书写了这些函数原型,#include命令并将#include标准库的所有头文件在"C
\ProgramFiles(x86)\MicrosoftVisualStudio\VC98\Include"目录下,可以打开此目录查看其中的内容,但千万不要试图修改它。
“C:\ProgramFiles(x86)”是VC安装目录,不同的机器可能不一样。
例3一个包含文件的实例本例中,format.h用#define定义了一组输出格式,在随后的主程序中用这些格式输出若干个变量的值。
编辑生成format上的方法与编辑普通C源程序一样,保存文件时给它指定合适的名称和后缀就可以了。
5.3 文件包含
printf("%d""%d""\n",a,b); "%d%d\n"主函数如下:# include"format.h"//可指定完整路径main(){ inta, b, c, d ; a = 1; b = 2; c = 3; d = 4; printf(D1,a); printf(D2, a, b); printf(D3, a, b, c); printf( D4,a,b,c,d); } 文件format.h如下:# defineNL "\n"#defineD "%d"#defineD1 D NL#defineD2 D D1#defineD3 D D2#defineD4 D D3展开连接运行结果:11 21 2 31 2 3 45.4 条件编译转下一部分
概念通常源程序中所有的行都参加编译,但有时希望源程序中的某些行只在满足一定条件下才进行编译,有时又希望满足某一条件时对一组语句进行编译,不满足这一条件时编译另一组语句,这就是“条件编译”。
二、作用划出源程序的一些片段,使预处理程序可以根据一定条件确定保留或丢掉某个片段,或确定从几个片段中选取哪一个片段保留下来。
三种使用格式
命令格式1根据标识符是否用#define命令定义过来选择保留“程序段1”或“程序段2”。
上面左右两种形式的选择方法正好相反。
5.4条件编译#ifdef标识符程序段1#else程序段2#endif#ifndef标识符程序段1#else程序段2#endif
命令格式2根据表达式值是否为真
命令格式3根据多个表达式值,从若干段中选一段。
5.4条件编译# if表达式程序段1# else程序段2#endif# if表达式1程序段1#elif表达式2程序段2#elif表达式3…# else程序段n#endif
5.4 条件编译
条件编译的选取语句操作是在预处理阶段完成的,因此,预处理命令中的表达式都应该是预处理阶段可以求值的表达式。
预处理完成之后,所有的预处理命令没有了,得到的是预处理命令展开或选择好的结果。
条件编译可有效地提高程序的可移植性,并广泛地应用在商业软件中,为一个程序提供各种不同的版本。
例4一个条件编译例子调试程序时
经常要打印一些跟踪信息,调试结束后,我们希望这些信息不再出现。
但是,这些信息对于我们将来修改程序、重新调试相当重要。
本例使用条件编译处理这些打印行,使用一个调试宏定义DEBUG来实现对调试行的选择控制。
条件编译的形式如下:#defineDEBUG1#ifDEBUG…//此处为打印行或调试行#endif
调试程序时
DEBUG定义为1;
调试结束,DEBUG定义为0。
可在所有调试及打印行处加入本例的条件编译命令。
下面是一段示例程序:#defineDEBUG1//宏名字用大写字母
#include<stdio.h>//在源程序中非常醒目main(){ #ifDEBUG//DEBUG为表达式printf("Thisistestingline\n"); #endifprintf("Thisisnormalline\n"); }本章内容不多但很实用,出现的预处理命令
#include,#if,#elif,#else,#endif,#ifdef,#idndef。下载地址:{{downurl}}
{{{a}}}
{{#b}}{{{b}}}
{{/b}} {{/title}} {{#nolog}}登陆注册
{{/nolog}} {{#djsx}}点我刷新
{{/djsx}} {{#gocz}} {{/gocz}} {{#ffqr}} {{/ffqr}}