用一个指定的标识符(即名字)来代表一个字符串,它的一般形式为
#define 标识符字符串
这就是已经介绍过的定义符号常量。如:
#define PI 3.1415926
它的作用是指定用标识符PI来代替“3.1415926”这个字符串,在编译预处理时,将程序中在该命令以后出现的所有的PI都用“3.1415926”代替。这种方法使用户能以一个简单的名字代替一个长的字符串,因此把这个标识符(名字)称为“宏名”,在预编译时将宏名替换成字符串的过程称为“宏展开”。#define是宏定义命令。
例9.1
# define PI 3.1415926
main()
{float I,s,r,v;
printf("input radius : ");
scanf("%f",&r);
I=2.0*PI*r;
s=PI*r*ri
v=4.0/3*PI* r*r*r;
printf("l=%10. 4f\ns=%10.4f\nv=%10.4f\n",l,s,v);
}
运行情况如下:
input radius :4
I=___25.1328
s=___ 50.2655
v=__150.7966
说明:
(1)宏名一般习惯用大写字母表示,以便与变量名相区别。但这并非规定,也可用小写字母。
(2)使用宏名代替一个字符串,可以减少程序中重复书写某些字符串的工作量。例如,如果不定义PI代表3.1415926,则在程序中要多处出现3.1415926,不仅麻烦,而且容易写错(或敲错),用宏名代替,简单不易出错,因为记住一个宏名(它的名字往往用容易理解的单词表示)要比记住一个无规律的字符串容易,而且在读程序时能立即知道它的含义,当需要改变某一个常量时,可以只改变#define命令行,一改全改。例如,定义数组大小,可以用
#define array_size 1000
int array[array_size];
先指定 array_size代表常量1000,因此数组array大小为1000,如果需要改变数组大小,只需改#define行:
# define array_size 500
使用宏定义,可以提高程序的通用性。
(3)宏定义是用宏名代替一个字符串,也就是作简单的置换,不作正确性检查。如果写成
# define PI 3.14159
即把数字1写成小写字母I,预处理时也照样代入,不管含义是否正确。也就是说预编译时不作任何语法检查。只有在编译已被宏展开后的源程序时才会发现错误并报错。
(4)宏定义不是C语句,不必在行末加分号。如果加了分号则会连分号一起进行置换。如:
#define PI 3.1415926;
area=PI*r*r;
经过宏展开后,该语句为
area=3.1415926:*r*r;
显然出现语法错误。
(5) #define 命令出现在程序中函数的外面,宏名的有效范围为定义命令之后到本源文件结束。通常,#define命令写在文件开头,函数之前,作为文件一部分,在此文件范围内有效。
(6)可以用#undef命令终止宏定义的作用域。例如:
由于#undef的作用,使G的作用范围在#undef行处终止,因此在f1函数中,G不再代表9.8。这样可以灵活控制宏定义的作用范围。
(7)在进行宏定义时,可以引用已定义的宏名,可以层层置换。
例9.2
#define R 3.0
# define PI 3.1415926
# define L 2 * PI* R
# define S PI * R * R
main()
{
printf("L=%f\nS=%f\n",L,S);
}
运行情况如下:
L=18.849556
S=28.274333
经过宏展开后,printf函数中的输出项L被展开为2*3.1415926* 3.0,S展开为
3.1415926*3.0*3.0,printf函数调用语句展开为
printí("L= %f\nS=%f\n",2* 3.1415926*3.0,3.1415926*3.0*3.0);
(8)对程序中用双撇号括起来的字符串内的字符,即使与宏名相同,也不进行置换。
如例 9.2 中的 printf函数内有两个L字符,一个在双撇号内,它不被宏置换,另一个在双撤号外,被宏置换展开。
(9)宏定义是专门用于预处理命令的一个专用名词,它与定义变量的含义不同,只作
字符替换,不分配内存空间。