第十五讲 宏定义

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

第十五讲宏定义、文件包含和条件编译

❑C语言提供的预处理功能主要有三种:

宏定义

文件包含

条件编译

❑为了区别预处理命令和C语句、定义和说明语句,规定:

预处理命令行必须在一行的开头;

必须以#开始;

每行末尾不能加分号。

1、宏定义

宏定义

1.1不带参数的宏定义

不带参数的宏定义命令形式为:

#define 宏名字符串

或#define 宏名

#define的作用是用指定的标识符(宏名)来代表字符串。其中#define是宏定义命令,宏名是一个标识符。

【例】输入一个圆的半径,计算并输出圆的面积和周长

#define PI 3.14159

main( )

{float l,s,r; /*l:周长,s:面积,r:半径*/

printf("Please input radius: ");

scanf("%f",&r); /*输入半径*/

l=2.0*r*PI; /*计算周长*/

s=PI*r*r; /*计算面积*/

printf("l=%10.4f\ns=%10.4f\n",l,s);

}

说明:

为了与变量名区别,建议宏名一般用大写字母。使用宏名代替一个

字符串,目的一是减少程序中某些重复使用字符串的书写量,其二

是增加程序的可读性。在编译预处理过程中会进行宏展开。

当宏定义在一行中写不下,需要在下一行继续时,只需在最后一个

字符后紧接一个反斜线“\”。注意在第二行开始不要有空格,否则空

格会一起被替换。

例如:#define LEAP_YEAR year % 4==0\

&& year %100!=0 || year % 400==0

在C语言中,宏定义一般写在程序开头。宏名的有效范围为定义命

令之后到本源文件结束,除非用#undef命令终止宏名的作用域。

对程序中用双引号括起来的字符串内的子串和用户标识符中的成分

不做替换。例如已定义:

同一个宏名不能重复定义,除非两个宏定义命令行完全一致。

1.2带参数的宏定义

形参表中的不同形参之间用逗号隔开,字符串中包含形参表中的参数,带参

数的宏定义命令形式为:

#define 宏名(形参表)字符串

【例6.2】分析下面程序的执行结果

#define M(x,y) (x*y)

main( )

{int a=2,b=3,c=4,d=5;

int x=M(a+b,c+d);

printf("%d",x);

}

程序运行结果为:19。宏替换结果为2+3*4+5。

说明:

在调用带参数的宏名时,注意实参和形参一定要一一对应,个数相

同,顺序一致。

和不带参数的宏定义相同,同一个宏名不能重复定义,除非两个宏

定义完全相同。

带参数的宏定义时,注意字符串中的括号的使用。比较下列两个宏

定义在替换后的不同:

其一其二

宏定义:#define MU(x,y) x*y #define MU(x,y) (x)*(y)

宏调用:6/MU(2+3,4+5) 6/MU(2+3,4+5)

结果:6/2+3*4+5即3+3+4+5=15 6/(2+3)*(4+5)即6/5+9

其三其四

宏定义:#define MU(x,y) (x*y) #define MU(x,y) ((x)*(y))

宏调用:6/MU(2+3,4+5) 6/MU(2+3,4+5)

结果:6/(2+3*4+5)即6/19 6/((2+3)*(4+5))即6/45

在宏调用中,实参不能替换括在双引号中的形参。

在进行宏定义时,可以引用已经定义过的宏名。

#define R 3.0

#define PI 3.14159

#define L 2.0*PI*R /*使用了已定义的宏名PI和R*/

#define S PI*R*R /*使用了已定义的宏名PI和R*/

【例】

#define PR(a) printf("%d\t",a)

#define PRINT(a) PR(a);printf("ok!") /*使用已定义的宏名PR(a)*/

main( )

{int i,a=1;

for(i=0;i<3;i++)

PRINT(a+i);

printf("\n");

}

终止宏定义

宏命令#undef用于终止宏定义的作用域。一般形式为:

#undef 宏名

例如:

#defin MU(x,y) ((x)*(y))

main( )

{ …

}

#undef MU(x,y)

function1( )

{ …

}

#undef 也可以用于一个函数的内部。

#define PI 3.14159

main( )

{ …

#undef PI

}

❑宏调用和函数调用的主要不同:

函数调用时,先求出实参的值,用实参的值代入形参;带参数的宏调用时,用实参的字符串代替形参,只是一种简单的字符替换。

函数调用在程序运行时完成,函数调用的过程由程序代码完成,分配临时的内存单元,占用运行时间;宏展开是在编译时由编译预处理程序完成的,仅

仅是一种简单的替换,因此宏调用不占有运行时间。

函数调用中要求实参和形参的类型一致;宏不存在类型问题,宏名无类型,它的参数也没有类型,只是一个符号代表。

函数调用一般会得到函数值。

2、文件包含

❑文件包含是指将另外一个源文件的内容包含到当前文件中来。

❑C语言提供了文件包含命令#include实现文件包含。#include命令的格式为:

#include “文件名” 或

#include <文件名>

❑说明:

一个include命令只能指定一个被包含文件,如果需要包含n个文件,可以用n个include命令。

#include命令应书写在所用文件的开头,故有时也把包含文件称作“头文件”。

头文件常用“h”作为后缀,当然也可以用其它后缀或没有后缀。

如果文件f1包含文件f2,f2又包含文件f3,这种情况叫做包含嵌套。包含嵌套的处理方式有两种,

C语言本身也为用户提供了许多库子程序,包括标准函数和宏定义。用户可以在自己的程序中使用这些库子程序完成一系列工作。与函数相关的信息存在

一些后缀为.h的头文件中。用户要想使用这些库函数,必须用#include命令

将有关头文件包含在自己的源程序中。

【例】

#include /*字符串函数strcpy相关头文件*/

#include /*输出函数puts相关头文件*/

main( )

相关文档
最新文档