《(中职)c语言技能教程第8章课件.ppt》由会员分享,可在线阅读,更多相关《(中职)c语言技能教程第8章课件.ppt(26页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、(中职)c语言技能教程第8章ppt课件第第8 8章章 编译预处理编译预处理C C语言技能教程语言技能教程第第 八章八章 8.1 技能技能1:掌握宏定义的使用掌握宏定义的使用8.2 技能技能2:读懂含有包含文件的程序读懂含有包含文件的程序8.3 技能技能3:读懂含有条件编译的程序读懂含有条件编译的程序 8.1 8.1 技能技能1 1【知识点】【知识点】1.1.预处理命令预处理命令预处理命令预处理命令#define#define定义了一个标识符,并在每次出现标定义了一个标识符,并在每次出现标定义了一个标识符,并在每次出现标定义了一个标识符,并在每次出现标识符时用一个字符串去代替它。这个标识符称为识
2、符时用一个字符串去代替它。这个标识符称为识符时用一个字符串去代替它。这个标识符称为识符时用一个字符串去代替它。这个标识符称为“宏名宏名宏名宏名”。而替换过程称为。而替换过程称为。而替换过程称为。而替换过程称为“宏代换宏代换宏代换宏代换”或或或或“宏展开宏展开宏展开宏展开”。2.2.宏定义是由源程序中的宏定义命令完成的。宏代换是由宏定义是由源程序中的宏定义命令完成的。宏代换是由宏定义是由源程序中的宏定义命令完成的。宏代换是由宏定义是由源程序中的宏定义命令完成的。宏代换是由预处理程序自动完成的。在预处理程序自动完成的。在预处理程序自动完成的。在预处理程序自动完成的。在C C语言中,语言中,语言中,
3、语言中,“宏宏宏宏”分为有参分为有参分为有参分为有参数和无参数两种。数和无参数两种。数和无参数两种。数和无参数两种。3.3.无参宏的宏名后不带参数。其定义的一般形式为:无参宏的宏名后不带参数。其定义的一般形式为:无参宏的宏名后不带参数。其定义的一般形式为:无参宏的宏名后不带参数。其定义的一般形式为:#define#define 标识符标识符标识符标识符 字符串字符串字符串字符串 8.1.1 不带参数的宏定义不带参数的宏定义8.1 8.1 技能技能1 1【典型例题】【典型例题】例例8.1 写出下面程序段的运行结果。写出下面程序段的运行结果。#define M (2*y+3)main()int z
4、,y;printf(请输入一个数请输入一个数:);scanf(%d,&y);z=2*M*M+5*M+1;printf(z=%dn,z);8.1.1 不带参数的宏定义不带参数的宏定义8.1 8.1 技能技能1 1【典型例题】【典型例题】例例8.2 写出下面程序段的运行结果。写出下面程序段的运行结果。#define PI 3.14159#define R 2.0#define S PI*R*Rmain()float z;z=3*S*S;printf(z=%fn,z);8.1.1 不带参数的宏定义不带参数的宏定义8.1 8.1 技能技能1 1【典型例题】【典型例题】例例8.3 写出下面程序段的运行结
5、果。写出下面程序段的运行结果。#define P printf#define D%dn#define F%fnmain()int a=1,b=2,c=3;float d=1.5,e=2.6,f=3.7;P(D F,a,d);P(D F,b,e);P(D F,c,f);8.1.1 不带参数的宏定义不带参数的宏定义8.1 8.1 技能技能1 1【点拨】【点拨】8.1.1 不带参数的宏定义不带参数的宏定义1.宏代换就是一种简单的代换,宏定义用宏名表示一个宏代换就是一种简单的代换,宏定义用宏名表示一个字符串,在宏展开时用这个字符串取代宏名,字符串中字符串,在宏展开时用这个字符串取代宏名,字符串中可以含
6、任何字符,可以是常数,也可以是表达式,预处可以含任何字符,可以是常数,也可以是表达式,预处理程序对它不作任何检查,因此如果有错误,只能在编理程序对它不作任何检查,因此如果有错误,只能在编译已经宏展开后的源程序时发现。译已经宏展开后的源程序时发现。2.在源程序中如果宏名用引号括起来,那么预处理程序在源程序中如果宏名用引号括起来,那么预处理程序则不对其作宏代换。则不对其作宏代换。3.宏定义允许嵌套,已经定义的宏名可以在宏定义的字宏定义允许嵌套,已经定义的宏名可以在宏定义的字符串中使用。由预处理程序在宏展开时层层代换。符串中使用。由预处理程序在宏展开时层层代换。8.1 8.1 技能技能1 1【点拨】
7、【点拨】8.1.1 不带参数的宏定义不带参数的宏定义4.一般宏名用大写字母表示,以利于同变量区别,但一般宏名用大写字母表示,以利于同变量区别,但也可以用小写字母表示。也可以用小写字母表示。5.数据类型也可用宏定义来表示,使书写方便,但在数据类型也可用宏定义来表示,使书写方便,但在使用时要小心,以免出错。使用时要小心,以免出错。6.宏定义不是说明,也不是语句,在行末不加分号。宏定义不是说明,也不是语句,在行末不加分号。如果加上分号,则连分号也一起置换。如果加上分号,则连分号也一起置换。7.宏定义必须写在函数的外面,其作用范围为从宏定宏定义必须写在函数的外面,其作用范围为从宏定义命令开始到当前源程
8、序结束。义命令开始到当前源程序结束。8.如果对如果对“输出格式输出格式”作宏定义,则可以减少书写麻作宏定义,则可以减少书写麻烦。烦。8.1 8.1 技能技能1 1【知识点】【知识点】1.1.在在在在C C语言中允许宏带有参数。在宏定义中的参数语言中允许宏带有参数。在宏定义中的参数语言中允许宏带有参数。在宏定义中的参数语言中允许宏带有参数。在宏定义中的参数称为形式参数,在宏调用中的参数称为实际参数。称为形式参数,在宏调用中的参数称为实际参数。称为形式参数,在宏调用中的参数称为实际参数。称为形式参数,在宏调用中的参数称为实际参数。对带参数的宏,在调用时,不仅宏展开,而且用对带参数的宏,在调用时,不
9、仅宏展开,而且用对带参数的宏,在调用时,不仅宏展开,而且用对带参数的宏,在调用时,不仅宏展开,而且用实际参数去代换形式参数。实际参数去代换形式参数。实际参数去代换形式参数。实际参数去代换形式参数。2.2.带参宏定义的一般形式为:带参宏定义的一般形式为:带参宏定义的一般形式为:带参宏定义的一般形式为:#define#define 宏名宏名宏名宏名(形参表形参表形参表形参表)字符串字符串字符串字符串 在字符串中含有各个形参。带参宏调用的一般形在字符串中含有各个形参。带参宏调用的一般形在字符串中含有各个形参。带参宏调用的一般形在字符串中含有各个形参。带参宏调用的一般形式为:式为:式为:式为:宏名宏名
10、宏名宏名(实参表实参表实参表实参表);8.1.2 带参数的宏定义带参数的宏定义8.1 8.1 技能技能1 1【典型例题】【典型例题】例例例例8.5 8.5 输入任意二个整数,输出最大值。输入任意二个整数,输出最大值。输入任意二个整数,输出最大值。输入任意二个整数,输出最大值。#define MAX(a,b)(ab)?a:b#define MAX(a,b)(ab)?a:bmain()main()int x,y,max;int x,y,max;printf(printf(请输入二个数请输入二个数请输入二个数请输入二个数););scanf(%d%d,&x,&y);scanf(%d%d,&x,&y);
11、max=MAX(x,y);max=MAX(x,y);printf(max=%dn,max);printf(max=%dn,max);8.1.2 带参数的宏定义带参数的宏定义8.1 8.1 技能技能1 1【典型例题】【典型例题】例例例例8.6 8.6 计算计算计算计算x+1x+1的平方值。的平方值。的平方值。的平方值。#define SQ(y)(y)*(y)#define SQ(y)(y)*(y)main()main()int x,sq;int x,sq;printf(printf(请输入一个数请输入一个数请输入一个数请输入一个数:);:);scanf(%d,&x);scanf(%d,&x);s
12、q=SQ(x+1);sq=SQ(x+1);printf(sq=%dn,sq);printf(sq=%dn,sq);8.1.2 带参数的宏定义带参数的宏定义8.1 8.1 技能技能1 1【点拨】【点拨】1.1.宏定义中的字符串内的形参通常要用括号括起来,以宏定义中的字符串内的形参通常要用括号括起来,以宏定义中的字符串内的形参通常要用括号括起来,以宏定义中的字符串内的形参通常要用括号括起来,以免出错。不但应该在参数的两侧加上括号,还应该在整免出错。不但应该在参数的两侧加上括号,还应该在整免出错。不但应该在参数的两侧加上括号,还应该在整免出错。不但应该在参数的两侧加上括号,还应该在整个字符串外加括号
13、。个字符串外加括号。个字符串外加括号。个字符串外加括号。2.2.在宏调用中的实参可以是表达式,而宏定义中的形参在宏调用中的实参可以是表达式,而宏定义中的形参在宏调用中的实参可以是表达式,而宏定义中的形参在宏调用中的实参可以是表达式,而宏定义中的形参仅仅是标识符。仅仅是标识符。仅仅是标识符。仅仅是标识符。3.3.在带参宏定义中,形参不分配内存单元,不必作类型在带参宏定义中,形参不分配内存单元,不必作类型在带参宏定义中,形参不分配内存单元,不必作类型在带参宏定义中,形参不分配内存单元,不必作类型定义。而宏调用中的实参有具体的值,要去代换形参,定义。而宏调用中的实参有具体的值,要去代换形参,定义。而
14、宏调用中的实参有具体的值,要去代换形参,定义。而宏调用中的实参有具体的值,要去代换形参,必须作类型说明。必须作类型说明。必须作类型说明。必须作类型说明。4.4.带参宏定义中,宏名和形参表之间不能有空格出现,带参宏定义中,宏名和形参表之间不能有空格出现,带参宏定义中,宏名和形参表之间不能有空格出现,带参宏定义中,宏名和形参表之间不能有空格出现,否则空格以后的字符将作为代换字符串的一部分。否则空格以后的字符将作为代换字符串的一部分。否则空格以后的字符将作为代换字符串的一部分。否则空格以后的字符将作为代换字符串的一部分。8.1.2 带参数的宏定义带参数的宏定义8.1 8.1 技能技能1 1【点拨】【
15、点拨】5.5.带参的宏和带参函数很相似,主要区别有:带参的宏和带参函数很相似,主要区别有:带参的宏和带参函数很相似,主要区别有:带参的宏和带参函数很相似,主要区别有:(1)(1)带参的宏是简单的字符替换;而函数调用时,先求实带参的宏是简单的字符替换;而函数调用时,先求实带参的宏是简单的字符替换;而函数调用时,先求实带参的宏是简单的字符替换;而函数调用时,先求实参,后代入形参。参,后代入形参。参,后代入形参。参,后代入形参。(2)(2)宏不存在类型问题;而函数中的实参和形参都要定义宏不存在类型问题;而函数中的实参和形参都要定义宏不存在类型问题;而函数中的实参和形参都要定义宏不存在类型问题;而函数
16、中的实参和形参都要定义一致的类型。一致的类型。一致的类型。一致的类型。(3)(3)用宏可以设法得到几个结果;而调用函数只可得到一用宏可以设法得到几个结果;而调用函数只可得到一用宏可以设法得到几个结果;而调用函数只可得到一用宏可以设法得到几个结果;而调用函数只可得到一个返回值。个返回值。个返回值。个返回值。(4)(4)宏代换不占用运行时间,只占编译时间;而函数调用宏代换不占用运行时间,只占编译时间;而函数调用宏代换不占用运行时间,只占编译时间;而函数调用宏代换不占用运行时间,只占编译时间;而函数调用则占运行时间。则占运行时间。则占运行时间。则占运行时间。8.1.2 带参数的宏定义带参数的宏定义8
17、.2 8.2 技能技能2 2【知识点】【知识点】文件包含命令的功能是把指定的文件插入该命令行位文件包含命令的功能是把指定的文件插入该命令行位文件包含命令的功能是把指定的文件插入该命令行位文件包含命令的功能是把指定的文件插入该命令行位置取代该命令行,从而把指定的文件包含进当前的源程序置取代该命令行,从而把指定的文件包含进当前的源程序置取代该命令行,从而把指定的文件包含进当前的源程序置取代该命令行,从而把指定的文件包含进当前的源程序文件中,并连成一个源文件。文件中,并连成一个源文件。文件中,并连成一个源文件。文件中,并连成一个源文件。其一般形式为其一般形式为其一般形式为其一般形式为#include
18、“#include“文件名文件名文件名文件名”或或或或#include#include 8.2 8.2 技能技能2 2【典型例题】【典型例题】#define P printf#define D%dn#define F%fn(1)文件文件 format.h#include“format.h”main()int a=1,b=2,c=3;float d=1.5,e=2.6,f=3.7;P(D F,a,d);P(D F,b,e);P(D F,c,f);(2)文件文件file1.c例例例例8.8 8.8 例例例例8.48.4程序的改写为:程序的改写为:程序的改写为:程序的改写为:8.2 8.2 技能技能
19、2 2【点拨】【点拨】1.1.一个一个一个一个includeinclude命令只能指定一个被包含文件,命令只能指定一个被包含文件,命令只能指定一个被包含文件,命令只能指定一个被包含文件,如果如果如果如果有多个文件需要包含,则要用多个有多个文件需要包含,则要用多个有多个文件需要包含,则要用多个有多个文件需要包含,则要用多个includeinclude命令。命令。命令。命令。2.2.包含命令中的文件名可以用尖括号括起来,也可包含命令中的文件名可以用尖括号括起来,也可包含命令中的文件名可以用尖括号括起来,也可包含命令中的文件名可以用尖括号括起来,也可以用双引号括起来。二者区别:尖括号表示仅在包以用双
20、引号括起来。二者区别:尖括号表示仅在包以用双引号括起来。二者区别:尖括号表示仅在包以用双引号括起来。二者区别:尖括号表示仅在包含文件目录中去查找含文件目录中去查找含文件目录中去查找含文件目录中去查找(包含目录是由用户在设置环包含目录是由用户在设置环包含目录是由用户在设置环包含目录是由用户在设置环境时设置的境时设置的境时设置的境时设置的);双引号则表示首先在当前的源文件双引号则表示首先在当前的源文件双引号则表示首先在当前的源文件双引号则表示首先在当前的源文件目录中查找,如果没有找到才到包含目录中去查找。目录中查找,如果没有找到才到包含目录中去查找。目录中查找,如果没有找到才到包含目录中去查找。目
21、录中查找,如果没有找到才到包含目录中去查找。3.3.在一个被包含的文件中又可以包含另一个文件。在一个被包含的文件中又可以包含另一个文件。在一个被包含的文件中又可以包含另一个文件。在一个被包含的文件中又可以包含另一个文件。8.3 8.3 技能技能3 3【知识点】【知识点】1.1.条件编译是按不同的条件编译不同的程序部分,由条件编译是按不同的条件编译不同的程序部分,由条件编译是按不同的条件编译不同的程序部分,由条件编译是按不同的条件编译不同的程序部分,由此产生不同的目标代码文件。条件编译有三种形式:此产生不同的目标代码文件。条件编译有三种形式:此产生不同的目标代码文件。条件编译有三种形式:此产生不
22、同的目标代码文件。条件编译有三种形式:(1)(1)第一种形式:第一种形式:第一种形式:第一种形式:#ifdef#ifdef 标识符标识符标识符标识符 程序段程序段程序段程序段1 1#else#else 程序段程序段程序段程序段2 2#endif#endif 功能:如果标识符已被功能:如果标识符已被#define命令定义过,则对程序命令定义过,则对程序段段1进行编译;否则对程序段进行编译;否则对程序段2进行编译。进行编译。8.3 8.3 技能技能3 3【知识点】【知识点】(2)(2)第二种形式:第二种形式:第二种形式:第二种形式:#ifndef#ifndef 标识符标识符标识符标识符 程序段程序
23、段程序段程序段1 1#else#else 程序段程序段程序段程序段2 2#endif#endif功能:如果标识符未被功能:如果标识符未被功能:如果标识符未被功能:如果标识符未被#define#define命令定义过,则对程序命令定义过,则对程序命令定义过,则对程序命令定义过,则对程序段段段段1 1进行编译,否则对程序段进行编译,否则对程序段进行编译,否则对程序段进行编译,否则对程序段2 2进行编译。进行编译。进行编译。进行编译。8.3 8.3 技能技能3 3【知识点】【知识点】(3)(3)第三种形式:第三种形式:第三种形式:第三种形式:#if#if 常量表达式常量表达式常量表达式常量表达式 程
24、序段程序段程序段程序段1 1#else#else 程序段程序段程序段程序段2 2#endif#endif其功能:如常量表达式的值为真其功能:如常量表达式的值为真其功能:如常量表达式的值为真其功能:如常量表达式的值为真(非非非非0)0),则对程序段,则对程序段,则对程序段,则对程序段1 1 进行编译,否则对程序段进行编译,否则对程序段进行编译,否则对程序段进行编译,否则对程序段2 2进行编译。因此程序可在不进行编译。因此程序可在不进行编译。因此程序可在不进行编译。因此程序可在不同的条件下完成不同的功能。同的条件下完成不同的功能。同的条件下完成不同的功能。同的条件下完成不同的功能。8.3 8.3
25、技能技能3 3【典型例题】【典型例题】例例例例8.9 8.9 输入一行字母,根据需要设置条件编译,使字母输入一行字母,根据需要设置条件编译,使字母输入一行字母,根据需要设置条件编译,使字母输入一行字母,根据需要设置条件编译,使字母全改为大写输出或小写输出。全改为大写输出或小写输出。全改为大写输出或小写输出。全改为大写输出或小写输出。#define LETTER 1main()char str30=THIS IS a string.,c;int i;i=0;while(i=A&c=a&c=z)c=c-32;#endif printf(%c,c);i+;8.3 8.3 技能技能3 3【典型例题】【
26、典型例题】例例例例8.10 8.10 输入一个数,根据需要设置条件编译,使之输出圆输入一个数,根据需要设置条件编译,使之输出圆输入一个数,根据需要设置条件编译,使之输出圆输入一个数,根据需要设置条件编译,使之输出圆面积或方块面积。面积或方块面积。面积或方块面积。面积或方块面积。#define R 1main()float c,r,s;printf(请输入一个数:请输入一个数:);scanf(%f,&c);#if R r=3.14159*c*c;printf(圆面积:圆面积:%fn,r);#else s=c*c;printf(方块面积:方块面积:%fn,s);#endif8.3 8.3 技能技能
27、3 3【点拨】【点拨】(1)如果条件选择的程序段很长,采用条件如果条件选择的程序段很长,采用条件编译的方法就很必要。编译的方法就很必要。(2)当条件编译段比较多时,可以极大地减当条件编译段比较多时,可以极大地减少被编译的语句、目标程序长度和运行时间少被编译的语句、目标程序长度和运行时间。理论与上机实习双指导理论与上机实习双指导一、学习目标一、学习目标本章重点介绍了编译预处理功能的宏定义、文件本章重点介绍了编译预处理功能的宏定义、文件包含和条件编译。通过本章学习,应达到以下要包含和条件编译。通过本章学习,应达到以下要求:求:1.熟练掌握二种宏定义的使用,并了解带参的宏熟练掌握二种宏定义的使用,并
28、了解带参的宏和带参函数的异同。和带参函数的异同。2.掌握文件包含命令,能够读懂含有包含文件的掌握文件包含命令,能够读懂含有包含文件的程序。程序。3.掌握条件编译命令,能够读懂含有条件编译的掌握条件编译命令,能够读懂含有条件编译的程序。程序。理论与上机实习双指导理论与上机实习双指导二、常见问题及上机注意事项二、常见问题及上机注意事项1.在宏定义的行末不加分号,如果加上分号则连在宏定义的行末不加分号,如果加上分号则连分号也一起置换。分号也一起置换。2.宏定义必须写在函数之外,其作用范围为从宏宏定义必须写在函数之外,其作用范围为从宏定义命令起到当前源程序结束。定义命令起到当前源程序结束。3.宏名在源
29、程序中若用引号括起来,则预处理程宏名在源程序中若用引号括起来,则预处理程序不对其作宏代换。序不对其作宏代换。理论与上机实习双指导理论与上机实习双指导二、常见问题及上机注意事项二、常见问题及上机注意事项4.带参宏定义中,宏名和形参表之间不能有空格带参宏定义中,宏名和形参表之间不能有空格出现。出现。如:如:#define SQ(y)(y)*(y)错写成:错写成:#define SQ (y)(y)*(y)5.宏定义中的字符串内的形参通常要用括号括起宏定义中的字符串内的形参通常要用括号括起来,以免出错。不但应该在参数的两侧加上括号,来,以免出错。不但应该在参数的两侧加上括号,还应该在整个字符串外加括号。还应该在整个字符串外加括号。如:如:#define SQ(y)(y)*(y)错写成:错写成:#define SQ(y)y*y6.一个一个include命令只能指定一个被包含文件。命令只能指定一个被包含文件。