- 8.3 宏定义指令
- define命令用于定义一个宏名。宏名是一个标识符,在源代码中遇到该标识符时,均以宏定义的串的内容代替该标识符。ANSI标准宏将定义的标识符称为“宏名”,而用定义的内容代替宏名的过程称为“宏替换”。#define命令用于定义宏名时,既可以带参数,也可以不带参数,下面分别介绍这两种情况。
- define标识符字符串
- define PI 3.14159
- define TURE 1
- define FALSE 0
- define begin{
- define end}
- define LONG_STR"this example show a very long string\
- define ONE 1
- define TWO ONE+ONE
- define THREE ONE+TWO
- define SIZE 10
- include<stdio.h>//头文件
- define STR“This is a test!\n”//宏定义字符串
- define标识符(参数表)字符串
- define FUN(A,B)2*A+B
- include<stdio.h>//头文件
- define PI 3.14159//宏定义PI=3.14159
- define L(R)2PIR//带参数的宏定义,用于计算周长
- define S(R)PIRR//带参数的宏定义,用于计算面积
8.3 宏定义指令
宏定义指令是指用一些标识符作为宏名,来代替其他一些符号或者常量的预处理命令。使用宏定义指令,可以减少程序中字符串输入的工作量,而且可以提高程序的可移植性。
宏名既可以是字符串或常数,也可以是带参数的宏。宏定义指令可分为带参数的宏定义和不带参数的宏定义。下面分别介绍用于宏定义的一些预处理命令。
8.3.1 #define命令
define命令用于定义一个宏名。宏名是一个标识符,在源代码中遇到该标识符时,均以宏定义的串的内容代替该标识符。ANSI标准宏将定义的标识符称为“宏名”,而用定义的内容代替宏名的过程称为“宏替换”。#define命令用于定义宏名时,既可以带参数,也可以不带参数,下面分别介绍这两种情况。
1.不带参数的宏定义
经常使用的宏定义指令是不带参数的,这种用法最简单。不带参数的宏定义的一般形式如下。
define标识符字符串
其中,“#define”是宏定义指令,“标识符”即定义的宏名,“字符串”是宏替换的对象。最常用的宏定义是用字符代替数值,示例如下。
define PI 3.14159
define TURE 1
define FALSE 0
执行这些宏定义指令后,在源程序的编译过程中,若遇到PI就用3.1415926代替,遇到TURE就用1代替,遇到FALSE就用0代替。然后再进行编译连接。
为了提高程序可读性,在使用不带参数的宏定义指令时,应注意以下几点。
❑宏定义中的标识符与C51的标识符表示相同,为了与变量名相区别,一般使用大写字母定义标识符,这样便于发现宏替换的位置。
❑宏定义不是语句,所以不要在后面加分号。如果加了分号,程序编译时,会将分号作为代替的字符串的一部分一起进行宏替换。
❑在宏定义定义的标识符和字符串之间可以有任意个空格或制表符。
❑若有多个宏定义指令,应将其集中放置于源文件的开头,而不是分散放置在整个程序中。
❑如果宏定义指令较多,也可将其集中起来放在一个单独的文件中,然后用#include指令来包含该文件即可使用这些宏定义。
❑用宏定义指令定义的标识符可以替代任意的字符串,甚至是一些语句,示例如下。
define begin{
define end}
❑如果所要替换的字符串长于一行,为了便于程序的阅读,可以在该行末尾用一反斜杠“\”进行续行,示例如下。
define LONG_STR"this example show a very long string\
split to two line."
本例中,因为宏定义的宏名较长,书写、阅读起来都不太方便,所以使用反斜杠“\”进行续行。
❑宏定义的宏名可以嵌套使用。当宏名定义后,即可成为其他宏名定义中的一部分,示例如下。
define ONE 1
define TWO ONE+ONE
define THREE ONE+TWO
本例中先宏定义了宏名ONE来替代1,接着在宏定义TWO时,使用两个ONE的和来替代1+1=2。宏定义THREE时,采用相同的方法。
❑宏定义可以用来表示数组的大小,这样便于数组的修改,示例如下。
define SIZE 10
int a[SIZE];
本例中,先宏定义SIZE为10,然后声明了一个整型数组a,其大小由SIZE来指定。这样若要修改数组的大小,直接修改宏定义SIZE的大小即可。
❑在源程序中,用双引号引起来的字符串不发生宏替换,即宏定义对程序中字符串不起作用。程序示例如下。
include<stdio.h>//头文件
define STR“This is a test!\n”//宏定义字符串
void main()//主函数
{
printf(STR);//输出宏定义字符串
printf(“STR”);//输出字符串
}
该程序可以在KeilµVision3集成开发环境中运行,其结果如下。
This is a test!
STR
本例中,先宏定义STR替代字符串“This is a test!\n”,然后在主函数中遇到STR即用字符串的内容来宏替换,在第二个输出语句中的STR,因为被双引号引起来了,所以不发生宏替换。
2.带参数的宏定义
宏定义指令也可以带参数,带参数的宏定义指令的一般形式如下。
define标识符(参数表)字符串
其中,“#define”是宏定义指令,“标识符”即定义的宏名,“参数表”是宏定义的形参列表,字符串是宏替换的对象。
在C51程序中遇到宏名时,不仅要进行字符串的替换,与之相连的形参也要由程序中的实参替换,示例如下。
define FUN(A,B)2*A+B
y=FUN(1,7);
本例中,先宏定义了FUN,在程序中遇到FUN时,用括号中的实参1和实参7分别替换了宏定义的形参A和形参B,即上面的语句等同于表达式,如下所示。
y=2*1+7;
带参数的宏定义和函数在程序中的作用十分相似。用宏替换代替函数,可以增加程序代码的执行速度,因为使用宏替换不用经过函数调用的过程,但是由于重复编码,会使程序代码的最终长度增加。带参数宏定义的程序示例如下。
include<stdio.h>//头文件
define PI 3.14159//宏定义PI=3.14159
define L(R)2PIR//带参数的宏定义,用于计算周长
define S(R)PIRR//带参数的宏定义,用于计算面积
void main()//主函数
{
int r;
r=10;//半径
printf(“L(10)=%f\n”,L(r));//输出周长
printf(“S(10)=%f\n”,S(r));//输出面积
}
该程序可以在KeilµVision3集成开发环境中运行,其结果如下所示。
L(10)=62.831800
S(10)=314.159000
在本例中,先采用不带参数的宏定义,定义PI来替换数3.14159;接着采用带参数的宏定义,来定义圆的周长和面积的计算。在主程序中,分别调用这两个宏定义来求解半径为10的圆的周长和面积。