1 简介
宏定义是C语言的三种预处理功能之一,另外两种预处理是文件包含和条件编译。
1.1 格式
宏定义的格式分为不带参数和带参数两种。
不带参数的格式为
#define 宏名 字符串
带参数的格式为
#define 宏名(参数表) 字符串
1.2 使用
宏展开是在预处理阶段完成的,这个阶段把宏名只是看作一个字符串,并不会有任何的计算发生。展开时,在宏名出现的地方只是简单地使用串来代替,并不会增添任何的符号。
2 使用时的注意事项
2.1 使用带参数的宏定义时,要使用完备的括号
由于宏定义只是简单的字符替换,宏的参数如果是复合结构,如果不使用括号,可能会产生意想不到的情况。如
#define ADD(a, b) a+b
或者
#define ADD(a, b) (a)+(b)
此时如果要计算ADD(a,b)*ADD(a,b),则会变成
a+b*a+b
或者
(a)+(b)*(a)+(b)
因此,对于宏定义要使用完备的括号
#define ADD(a, b) ((a)+(b))
2.2 使用宏定义时,不允许参数发生变化
如果在使用宏定义时,参数进行了自增或者自减变化,则在宏定义展开时对其参数的多次自增或自减变化,导致意想不到的情况。如
#define SQUARE(a) ((a)*(a))
int nValue = 10;
int nSquare = SQUARE(nValue++);
此时,nSquare的值是110,而nValue的值是12。
所以,为了避免出现这种情况,最简单有效的方法是保证宏定义的参数不发生变化。
2.3 用大括号将宏定义的多条表达式括起来
如果宏定义包含多条表达式,一定要用大括号将其括起来。如果没有这个大括号,宏定义中多条表达式很可能只有一条会被执行。
#define INIT(a, b, c) a=0;b=1;c=2;
for(int i=0; i<10; ++i)
INIT(A[i].a, B[i].b, C[i].c);
简单的字符代替,for循环变为
for(int i=0; i<10; ++i)
A[i].a = 0;
B[i].b = 1;
C[i].c = 2;
此时,程序会因为i超出作用域范围而报错。如果把INIT宏写成
#define INIT(a, b, c) {a=0;b=1;c=2;}
则可以完成对A、B、C数组的初始化。