8编译预处理[归.pdf
《8编译预处理[归.pdf》由会员分享,可在线阅读,更多相关《8编译预处理[归.pdf(14页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、8 编译预处理 本章重点:宏定义命令 条件编译命令 文件包含命令 本章难点:带参宏定义 条件编译 在 C语言源程序中,除了为实现程序功能而使用的声明语句和执行语句之外,还可以使用编译预处理命令。所谓编译预处理是指,在对源程序进行编译之前,先对源程序中的编译预处理命令进行处理;然后再将处理的结果和源程序一起进行编译,得到目标代码。C 语言提供的编译预处理命令主要有宏定义、条件编译和文件包含等三种。为了能够和一般 C语句区别开来,编译预处理命令以“#”号开头。它占用一个单独的书写行,命令行末尾没有分号。编译预处理是语言的一个重要功能,合理地使用编译预处理功能编写的程序便于阅读、修改、调试和移植,也
2、有利于模块化程序设计。8.1 宏定义 宏定义是指将一个标识符(又称宏名)定义为一个字符串(或称替换文本)。在编译预处理时,对程序中出现的所有宏名都用相应的替换文本去替换,这称为“宏替换”或“宏展开”。在语言中,“宏定义”可分为无参宏定义和带参宏定义两种。8.1.1 无参宏定义 无参宏定义即定义没有参数的“宏”,其一般形式为:#define 标识符 替换文本 其中#define表示该语句行是宏定义命令,“标识符”为所定义的宏名,习惯上宏名用大写字母表示;“替换文本”可以是常量、关键字、表达式、语句等任意字符串。在 define、宏名和替换文本之间分别用空格隔开。#define命令可以不包含“替换
3、文本”,此时仅说明宏名已被定义,以后可以使用。第 2 章介绍的符号常量的定义就是一种无参宏定义。例 8-1 用无参宏定义计算s=3*(y*y+3*y)+4*(y*y+3*y)+5*(y*y+3*y)。算法分析:在计算式子中出现了三个(y*y+3*y),为减少书写量,可使用宏定义。程序如下:#define M(y*y+3*y)main()int s,y;printf(Please input a number:);scanf(%d,&y);s=3*M+4*M+5*M;printf(s=%dn,s);运行情况如下:Please input a number:4 s=336 在上面程序的语句s=3*
4、M+4*M+5*M;中引用了3 次宏 M,经“宏展开”后该语句变为:s=3*(y*y+3*y)+4*(y*y+3*y)+5*(y*y+3*y);符合题目要求。注意在宏定义中替换文本(y*y+3*y)两边的括号不能少,否则会产生错误。如改为以下定义:#difine M y*y+3*y 则在宏展开时将得到下述语句:s=3*y*y+3*y+4*y*y+3*y+5*y*y+3*y;显然与原题意要求不符,计算结果当然是错误的。因此在进行宏定义时必须注意,应保证在宏代换之后不发生错误。对于无参宏定义还要说明以下几点:(1)习惯上宏名用大写字母表示,以便与变量名区别开。但这并非规定,也允许使用小写字母。(2
5、)用替换文本替换宏名只是一种简单的直接替换,替换文本中可以包含任意字符,系统在进行编译预处理时对它不作任何检查。例如:#define PI 3.l415926 即不小心将替换文本中的第一个数字“1”错写成了小写字母“l”,不再表示圆周率的近似值,预处理时仍然把PI 替换成 3.l415926,而不管含义如何。在编译时才发现错误并报错。(3)宏定义不是声明或执行语句,在行末不要加分号,如果加上分号则连分号也一起替换。(4)一个#define只能定义个宏,且一行只能定义一个宏。若需要定义多个宏就要使用多个#define,并写在多行上。(5)宏定义时如果一行写不下,可用“”续行。例如:#define
6、 PI 3.1415926 /*正确*/#define PI 3.1415 926 /*正确*/(6)宏定义原则上可以出现在源程序的任何地方,但通常写在函数之外,其作用域为文档编码:CX1B9I10I1C9 HA5G6F4B8Y1 ZI6S10Q4Q9X2文档编码:CX1B9I10I1C9 HA5G6F4B8Y1 ZI6S10Q4Q9X2文档编码:CX1B9I10I1C9 HA5G6F4B8Y1 ZI6S10Q4Q9X2文档编码:CX1B9I10I1C9 HA5G6F4B8Y1 ZI6S10Q4Q9X2文档编码:CX1B9I10I1C9 HA5G6F4B8Y1 ZI6S10Q4Q9X2文档编码
7、:CX1B9I10I1C9 HA5G6F4B8Y1 ZI6S10Q4Q9X2文档编码:CX1B9I10I1C9 HA5G6F4B8Y1 ZI6S10Q4Q9X2文档编码:CX1B9I10I1C9 HA5G6F4B8Y1 ZI6S10Q4Q9X2文档编码:CX1B9I10I1C9 HA5G6F4B8Y1 ZI6S10Q4Q9X2文档编码:CX1B9I10I1C9 HA5G6F4B8Y1 ZI6S10Q4Q9X2文档编码:CX1B9I10I1C9 HA5G6F4B8Y1 ZI6S10Q4Q9X2文档编码:CX1B9I10I1C9 HA5G6F4B8Y1 ZI6S10Q4Q9X2文档编码:CX1B9
8、I10I1C9 HA5G6F4B8Y1 ZI6S10Q4Q9X2文档编码:CX1B9I10I1C9 HA5G6F4B8Y1 ZI6S10Q4Q9X2文档编码:CX1B9I10I1C9 HA5G6F4B8Y1 ZI6S10Q4Q9X2文档编码:CX1B9I10I1C9 HA5G6F4B8Y1 ZI6S10Q4Q9X2文档编码:CX1B9I10I1C9 HA5G6F4B8Y1 ZI6S10Q4Q9X2文档编码:CX1B9I10I1C9 HA5G6F4B8Y1 ZI6S10Q4Q9X2文档编码:CX1B9I10I1C9 HA5G6F4B8Y1 ZI6S10Q4Q9X2文档编码:CX1B9I10I1C
9、9 HA5G6F4B8Y1 ZI6S10Q4Q9X2文档编码:CX1B9I10I1C9 HA5G6F4B8Y1 ZI6S10Q4Q9X2文档编码:CX1B9I10I1C9 HA5G6F4B8Y1 ZI6S10Q4Q9X2文档编码:CX1B9I10I1C9 HA5G6F4B8Y1 ZI6S10Q4Q9X2文档编码:CX1B9I10I1C9 HA5G6F4B8Y1 ZI6S10Q4Q9X2文档编码:CX1B9I10I1C9 HA5G6F4B8Y1 ZI6S10Q4Q9X2文档编码:CX1B9I10I1C9 HA5G6F4B8Y1 ZI6S10Q4Q9X2文档编码:CX1B9I10I1C9 HA5G
10、6F4B8Y1 ZI6S10Q4Q9X2文档编码:CX1B9I10I1C9 HA5G6F4B8Y1 ZI6S10Q4Q9X2文档编码:CX1B9I10I1C9 HA5G6F4B8Y1 ZI6S10Q4Q9X2文档编码:CX1B9I10I1C9 HA5G6F4B8Y1 ZI6S10Q4Q9X2文档编码:CX1B9I10I1C9 HA5G6F4B8Y1 ZI6S10Q4Q9X2文档编码:CX1B9I10I1C9 HA5G6F4B8Y1 ZI6S10Q4Q9X2文档编码:CX1B9I10I1C9 HA5G6F4B8Y1 ZI6S10Q4Q9X2文档编码:CX1B9I10I1C9 HA5G6F4B8Y
11、1 ZI6S10Q4Q9X2文档编码:CX1B9I10I1C9 HA5G6F4B8Y1 ZI6S10Q4Q9X2文档编码:CX1B9I10I1C9 HA5G6F4B8Y1 ZI6S10Q4Q9X2文档编码:CX1B9I10I1C9 HA5G6F4B8Y1 ZI6S10Q4Q9X2文档编码:CX1B9I10I1C9 HA5G6F4B8Y1 ZI6S10Q4Q9X2文档编码:CX1B9I10I1C9 HA5G6F4B8Y1 ZI6S10Q4Q9X2文档编码:CX1B9I10I1C9 HA5G6F4B8Y1 ZI6S10Q4Q9X2文档编码:CX1B9I10I1C9 HA5G6F4B8Y1 ZI6S
12、10Q4Q9X2文档编码:CX1B9I10I1C9 HA5G6F4B8Y1 ZI6S10Q4Q9X2文档编码:CX1B9I10I1C9 HA5G6F4B8Y1 ZI6S10Q4Q9X2文档编码:CX1B9I10I1C9 HA5G6F4B8Y1 ZI6S10Q4Q9X2文档编码:CX1B9I10I1C9 HA5G6F4B8Y1 ZI6S10Q4Q9X2文档编码:CX1B9I10I1C9 HA5G6F4B8Y1 ZI6S10Q4Q9X2文档编码:CX1B9I10I1C9 HA5G6F4B8Y1 ZI6S10Q4Q9X2文档编码:CX1B9I10I1C9 HA5G6F4B8Y1 ZI6S10Q4Q9
13、X2从宏定义命令起到源程序文件结束。如要终止其作用域可使用#undef命令,其用法为:#undef 标识符如:#undef PI(7)宏名在源程序中若用双撇号括起来,则在编译预处理时不对其作宏替换。也就是说,宏名被双撇号括起来时,仅作为一般字符串使用。例 8-2 宏替换的选择性。#define PI 3.1415926 main()printf(PI is%9.7f.n,PI);程序运行结果为:PI is 3.1415926.例 8-2 中定义宏名PI 表示 3.1415926,但在 printf函数中第一个PI 被双撇号括起来,因此不进行宏替换,只把该“PI”当普通的字符串处理,而第二个PI
14、 没有被双撇号括起来,因此被替换成了3.1415926。(8)宏定义允许嵌套,在宏定义的替换文本中可以使用已经定义过的宏名。在宏展开时层层替换。例如:#define PI 3.1415926#define S PI*r*r /*PI是已定义的宏名*/对语句:printf(%f,S);在宏替换后变为:printf(%f,3.1415926*r*r);使用无参宏定义还可以实现程序的个性化(如用自己所习惯的符号表示数据类型或输出格式等),使程序的书写、阅读更加方便。例 8-3 用无参宏定义表示常用的数据类型和输出格式。#define INTEGER int#define REAL float#def
15、ine P printf#define D%dn#define F%fnmain()INTEGER a=5,c=8,e=11;REAL b=3.8,d=9.7,f=21.08;P(D F,a,b);P(D F,c,d);P(D F,e,f);文档编码:CX1B9I10I1C9 HA5G6F4B8Y1 ZI6S10Q4Q9X2文档编码:CX1B9I10I1C9 HA5G6F4B8Y1 ZI6S10Q4Q9X2文档编码:CX1B9I10I1C9 HA5G6F4B8Y1 ZI6S10Q4Q9X2文档编码:CX1B9I10I1C9 HA5G6F4B8Y1 ZI6S10Q4Q9X2文档编码:CX1B9I
16、10I1C9 HA5G6F4B8Y1 ZI6S10Q4Q9X2文档编码:CX1B9I10I1C9 HA5G6F4B8Y1 ZI6S10Q4Q9X2文档编码:CX1B9I10I1C9 HA5G6F4B8Y1 ZI6S10Q4Q9X2文档编码:CX1B9I10I1C9 HA5G6F4B8Y1 ZI6S10Q4Q9X2文档编码:CX1B9I10I1C9 HA5G6F4B8Y1 ZI6S10Q4Q9X2文档编码:CX1B9I10I1C9 HA5G6F4B8Y1 ZI6S10Q4Q9X2文档编码:CX1B9I10I1C9 HA5G6F4B8Y1 ZI6S10Q4Q9X2文档编码:CX1B9I10I1C9
17、 HA5G6F4B8Y1 ZI6S10Q4Q9X2文档编码:CX1B9I10I1C9 HA5G6F4B8Y1 ZI6S10Q4Q9X2文档编码:CX1B9I10I1C9 HA5G6F4B8Y1 ZI6S10Q4Q9X2文档编码:CX1B9I10I1C9 HA5G6F4B8Y1 ZI6S10Q4Q9X2文档编码:CX1B9I10I1C9 HA5G6F4B8Y1 ZI6S10Q4Q9X2文档编码:CX1B9I10I1C9 HA5G6F4B8Y1 ZI6S10Q4Q9X2文档编码:CX1B9I10I1C9 HA5G6F4B8Y1 ZI6S10Q4Q9X2文档编码:CX1B9I10I1C9 HA5G6
18、F4B8Y1 ZI6S10Q4Q9X2文档编码:CX1B9I10I1C9 HA5G6F4B8Y1 ZI6S10Q4Q9X2文档编码:CX1B9I10I1C9 HA5G6F4B8Y1 ZI6S10Q4Q9X2文档编码:CX1B9I10I1C9 HA5G6F4B8Y1 ZI6S10Q4Q9X2文档编码:CX1B9I10I1C9 HA5G6F4B8Y1 ZI6S10Q4Q9X2文档编码:CX1B9I10I1C9 HA5G6F4B8Y1 ZI6S10Q4Q9X2文档编码:CX1B9I10I1C9 HA5G6F4B8Y1 ZI6S10Q4Q9X2文档编码:CX1B9I10I1C9 HA5G6F4B8Y1
19、 ZI6S10Q4Q9X2文档编码:CX1B9I10I1C9 HA5G6F4B8Y1 ZI6S10Q4Q9X2文档编码:CX1B9I10I1C9 HA5G6F4B8Y1 ZI6S10Q4Q9X2文档编码:CX1B9I10I1C9 HA5G6F4B8Y1 ZI6S10Q4Q9X2文档编码:CX1B9I10I1C9 HA5G6F4B8Y1 ZI6S10Q4Q9X2文档编码:CX1B9I10I1C9 HA5G6F4B8Y1 ZI6S10Q4Q9X2文档编码:CX1B9I10I1C9 HA5G6F4B8Y1 ZI6S10Q4Q9X2文档编码:CX1B9I10I1C9 HA5G6F4B8Y1 ZI6S1
20、0Q4Q9X2文档编码:CX1B9I10I1C9 HA5G6F4B8Y1 ZI6S10Q4Q9X2文档编码:CX1B9I10I1C9 HA5G6F4B8Y1 ZI6S10Q4Q9X2文档编码:CX1B9I10I1C9 HA5G6F4B8Y1 ZI6S10Q4Q9X2文档编码:CX1B9I10I1C9 HA5G6F4B8Y1 ZI6S10Q4Q9X2文档编码:CX1B9I10I1C9 HA5G6F4B8Y1 ZI6S10Q4Q9X2文档编码:CX1B9I10I1C9 HA5G6F4B8Y1 ZI6S10Q4Q9X2文档编码:CX1B9I10I1C9 HA5G6F4B8Y1 ZI6S10Q4Q9X
21、2文档编码:CX1B9I10I1C9 HA5G6F4B8Y1 ZI6S10Q4Q9X2文档编码:CX1B9I10I1C9 HA5G6F4B8Y1 ZI6S10Q4Q9X2文档编码:CX1B9I10I1C9 HA5G6F4B8Y1 ZI6S10Q4Q9X2文档编码:CX1B9I10I1C9 HA5G6F4B8Y1 ZI6S10Q4Q9X2文档编码:CX1B9I10I1C9 HA5G6F4B8Y1 ZI6S10Q4Q9X2文档编码:CX1B9I10I1C9 HA5G6F4B8Y1 ZI6S10Q4Q9X2文档编码:CX1B9I10I1C9 HA5G6F4B8Y1 ZI6S10Q4Q9X2文档编码:
22、CX1B9I10I1C9 HA5G6F4B8Y1 ZI6S10Q4Q9X2程序运行结果为:5 3.800000 8 9.700000 11 21.080000 8.1.2 带参宏定义 语言允许“宏”带有参数。在宏定义中的参数称为形式参数,在引用带参宏时给出的参数称为实际参数。带参宏定义的一般形式为:#define 宏名(形参表)替换文本其中,形参表由一个或多个形参组成,各形参之间用逗号隔开,替换文本中通常应包括有形参。引用带参宏的一般形式为:宏名(实参表)带参宏定义展开时先把宏引用替换为替换文本,再将替换文本中出现的形参用实参代替。例如下面的宏定义和引用:#define M(y)y*y+3*y
23、 /*宏定义*/k=M(5);/*宏引用*/宏展开时,先用y*y+3*y 替换 M(5),再将替换文本中的形参y 用实参 5 代替,最终得到:k=5*5+3*5;例 8-4 用带参宏定义求两数中的大者。#define MAX(a,b)(ab)?a:b main()int x,y,max;printf(input two numbers(x,y):);scanf(%d,%d,&x,&y);max=MAX(x,y);printf(max=%dn,max);程序运行情况如下:input two numbers(x,y):5,6 max=6 这里的宏MAX(a,b)既可以比较int型数据,也可以比较f
24、loat型、char 型等各种类型数据。若要比较float型数据,只需将程序第3 行改为:文档编码:CX1B9I10I1C9 HA5G6F4B8Y1 ZI6S10Q4Q9X2文档编码:CX1B9I10I1C9 HA5G6F4B8Y1 ZI6S10Q4Q9X2文档编码:CX1B9I10I1C9 HA5G6F4B8Y1 ZI6S10Q4Q9X2文档编码:CX1B9I10I1C9 HA5G6F4B8Y1 ZI6S10Q4Q9X2文档编码:CX1B9I10I1C9 HA5G6F4B8Y1 ZI6S10Q4Q9X2文档编码:CX1B9I10I1C9 HA5G6F4B8Y1 ZI6S10Q4Q9X2文档编
25、码:CX1B9I10I1C9 HA5G6F4B8Y1 ZI6S10Q4Q9X2文档编码:CX1B9I10I1C9 HA5G6F4B8Y1 ZI6S10Q4Q9X2文档编码:CX1B9I10I1C9 HA5G6F4B8Y1 ZI6S10Q4Q9X2文档编码:CX1B9I10I1C9 HA5G6F4B8Y1 ZI6S10Q4Q9X2文档编码:CX1B9I10I1C9 HA5G6F4B8Y1 ZI6S10Q4Q9X2文档编码:CX1B9I10I1C9 HA5G6F4B8Y1 ZI6S10Q4Q9X2文档编码:CX1B9I10I1C9 HA5G6F4B8Y1 ZI6S10Q4Q9X2文档编码:CX1B
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 编译 预处理
限制150内