Chinaunix首页 | 论坛 | 博客
  • 博客访问: 68095
  • 博文数量: 22
  • 博客积分: 1406
  • 博客等级: 上尉
  • 技术积分: 190
  • 用 户 组: 普通用户
  • 注册时间: 2008-10-13 13:18
文章分类

全部博文(22)

文章存档

2011年(1)

2010年(21)

我的朋友

分类: C/C++

2010-03-06 12:04:26

#define命令

#define命令主要可以实现两种功能:
1) 符号常量定义
2) 宏定义

符号常量定义

在介绍符号常量定义之前,首先分析如下的程序。
例11-1 输入全班20个同学的C语言成绩,并计算出最高分同学的姓名和成绩,并计算出全班C语言成绩的平均分。
#include "stdio.h"
void main()
{
float fAvg; /*平均成绩 */
float fMax; /*最高成绩 */
int iMax;
float fSum;
int i;
/*C语言成绩(20人) */
float fCScore[20]={78.5,65,89,65,45,62,89,99,85,85, 100,58,98,86,68,66,85.5,89.5,75,76};
/*全班同学的姓名(20人) */
char chNames[][20]= { "Maofen","LiuTao","Wangyu","Songbou", "Liyang", "Wangming","Renhon", "Wuyong","Luming","Sunce","Zhangjie","Yuanquan", "Yangjing","Yubing","XingWen","Huangxing","Dingwen","Quyang","Liufeng","Hanhan"
};
/*计算总分*/
fSum=0;
for(i=0;i<20;i++)
fSum=fSum+fCScore[i];
/*计算平均分*/
fAvg =fSum/20;
/*计算最高分*/
fMax = fCScore[0];
iMax=0;
for(i=0;i<20;i++)
{
if(fMax
{
iMax=i;
fMax= fCScore[i];
}
}
/*输出信息*/
printf("\nThe Score of C Programming Language\n");
printf("The first is %10s \n",chNames[iMax]);
printf("The Score is %10.2f \n",fCScore[iMax]);
printf("The Average is %10.2f \n",fAvg);
}
在上面的程序中,20是一整型常量,代表全班同学的总人数。根据求解问题的需要,20出现了多次。如果将此程序修改,以便处理一个具有25个同学的班级,则需要进行多处的改动。在实际的软件开发中,一个简单的常量可能在整个软件的不同部分出现上百次或上千次,并可能代表不同的信息。在移植过程中,采用手工修改,十分容易出现错误。因此C语言中引入了符号常量,形式如下:
#define 符号常量名称 替换文本
其中#define 为预编译命令,“替换文本”为“符号常量”所代表的字符序列集合,可以为任意字符的组合。在程序代码被编译之前,编译系统自动将所有符号常量出现的位置,被其代表的“替换文本”无条件的替换,然后再进行语法检查和编译。因此利用符号常量,例11-1可改写为
#include "stdio.h"
#define STUDENT_COUNT 20
void main()
{
……
/*C语言成绩(20人) */
float fCScore[STUDENT_COUNT ]={…};
char chNames[][STUDENT_COUNT ]={ …};
fSum=0;
for(i=0;i
fSum=fSum+fCScore[i];
fAvg =fSum/STUDENT_COUNT ;
for(i=0;i
{
……
}
}
为了节省空间,上述程序仅仅显示了修改后的部分。结合例11-1,将所有20用STUDENT_COUNT替换即可。其中
#define STUDENT_COUNT 20
是定义符号常量STUDENT_COUNT,其替换文本为20,代表20这样一个字符序列集合,在程序编译时,所有STUDENT_COUNT出现的位置均被20 无条件的替换。
如果将上述程序修改为处理具有30位同学的班级,只需修改定义
#define STUDENT_COUNT 30
即可。从上面的分析可以看出,恰当的使用符号常量可以增强程序的可移植能力。
提示 符号常量出现的位置,最终将无条件替换为其代表的字符序列集合,并不做语法检查。在编译程序时再进行语法检查。另外,符号常量定义的末尾不能有分号,与普通的程序语句不同。
符号常量的所带代表字符序列集合,可以为空,形式如下:
#define 编译标志
此命令的主要用途是引入编译标志,根据不同的编译标志,编译系统可以完成对不同代码段的编译。例如下面的程序
例11-2 在Windows系统中int 为32位数,在Dos中long为32位数。为了程序在两个系统中移植,可以定义INT32,保证在两种系统中利用INT32声明的变量为32位整型数。
#include "stdio.h"
#ifdef MY_DOS
#define INT16 int
#define INT32 long
#endif
#ifdef MY_WIN32
#define INT16 short
#define INT32 int
#endif
void main()
{
INT32 a;
a=32;
printf("%ld",a);
}
其中MY_WIN32和MY_DOS为编译标志,本段程序的主要目的是保证INT32类型数总是32位的整型数,在DOS系统中编译的时候增加代码
#define MY_DOS
此时INT32代表long。
在Windows系统下编译的时候,修改为
#define MY_WIN32
此时INT32代表int。
提示 符号常量与变量常常混淆。符号常量是一个有名字,因此其与变量相似,但是其值在程序运行过程中不能更改,与常量类似。
一般符号常量的名称采用大写字母,用于区分变量。
将常用的常量定义为符号常量是一种良好的设计习惯。

宏定义

C语言还提供另外一种带参数的#define命令,其英文为macro,一般翻译为宏。其形式如下:
#define 宏(参数列表) 替换文本
其中一般称“替换文本”为宏定义。例如
#define Sum(a,b) a+b
中Sum为宏,a,b为参数列表,a+b为宏定义。在下面的代码中
a=Sum(2,3);
在编译阶段,被替换为
a=2+3;
然后,再编译成可执行代码。
例10-3 定义宏FAILED用于检测数据的正确性。
#define FAILED(Status) ((Status)<0)
#include "stdio.h"
void main()
{
int d;
printf ("Please input a integer number(n>0)\n");
do
{
scanf("%d" ,&d);
}while(FAILED(d));
}
其中while(FAILED(d))在编译之前被无条件替换为while(d<0)。
宏定义和调用在形式与函数比较相似,但是原理是不同。
例10-4 定义Add函数实现两个数的乘法。
double Add(int a,int b)
{
return a*b;
}
void main()
{
double a,b;
double e,f;
a=3;
b=2;
e=Add(a,2);
f=Add(b+1,2);
printf("e=%ff=%f",e,f);
}
程序的运行结果如下
e=6.000000f=6.000000
在下面代码与上面的代码类似,但是运行结果不同。
例10-5 定义Add宏实现两个数的乘法。
#define Add(a,b)? a*b
void main()
{
double a,b;
double e,f;
a=3;
b=2;
e=Add(a,2);
f=Add(b+1,2);
printf("e=%f,f=%f",e,f);
}
程序的运行结果如下
e=6.000000,f=4.000000
在编译之前,系统做如下的处理:
e=Add(a,2)替换为e=a*2;
f=Add(b+1,2)替换为f=b+1*2;

因此在使用宏的时候,一定要注意与函数区分。首先宏是一种预编译指令,函数为程序指令。其次宏的作用是定义一种带参数的代码替换方法,在编译之后不会形成独立的代码段;而函数在编译之后会形成相对独立的代码段。
提示 函数定义是将一块公共的代码封装成一个函数,系统编译之后,此部分的机器指令依然作为一个相对对立的代码段。宏的定义仅仅是定义一个带参数的文本替换编译指令,在编译的时候所有的宏将被其代表的信息替换,而在编译之后,对应的机器指令不独立存在。
宏的使用与函数的调用不同。宏的使用发生在程序代码编译成为机器指令之前,而函数的调用发生在程序运行的时候。函数调用会产生额外系统开销,而宏的使用会加大程序代码量,函数的使用会减少程序的代码量。使用宏可以获得更高的代码运行效率,因为其不存在函数调用。
阅读(826) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~