宏定义有两种:不带参数的宏定义和带参数的宏定义。

不带参数的宏定义

不带参数宏定义的一般形式为:

#define  宏名 字符串

#define  PI  3.1415926

 main() 

{

float  area, r;

printf (“area=%f”,PI*r*r);

}

以上程序中以宏名PI来替换字符串3.1415926,这样做的好处是显然的,一是可以简化程序,二是便于修改。

说明:

1. 宏定义一般写在程序的开头。

2. 宏名的命名规则同变量名,一般习惯用大写字母如PI,以区别程序中的变量。

3. 宏名的有效范围是从宏定义开始到本源程序文件结束,或遇到预处理命令#undef时止。

#define  PI  3.14

宏PI的有效范围

 main( )

 {

 . . .

 }

  #undef  PI

f1( )

{

. .

}

4. 宏定义不但可以定义常量,还可以定义c语句和表达式等。另外宏定义还可以嵌套定义。即在宏定义中的字符串

以引用被另一个宏定义所定义的宏名。  #define  PI  3.14

#define  R  30

 #define  AREA  PI *R*R

 #define  PRN  printf(“/n”); 

     main()

     {

        printf(“%lf”,AREA);

       PRN

     }

5. 宏代换只是指定字符串的简单替换,不作任何语法检查,只是在编译已被展开的源程序时,才可能报错。如后面

分号,则连分号一起置换。如上例第四句。

6.不能替换双引号中与宏名相同的字符串,也不能用户标识符中与宏名相同的成分。如printf(“PI”)中的PI,和PIR

的PI与前面定义过的宏名相同,但它们不能用3.14来替换。

带参数的宏定义            

带参数的宏定义的一般形式如下:

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

  例如  #define  M(a,b)  a*b

                 . . .

                 s=M(3,5);  

     说明:

1. 上例宏调用的结果是s=3*5=15,即用实参3,5来代替形参a,b,实参个数要与形参个数相同,而没有类型要求,

点与函数调用不同,函数调用要求参数类型一致。

2. 如宏调用改为s=M(3+2,5+1),则调用为s=3+2*5+1,显然与我们希望的结果不符,这时应将宏定义改为 

#define  M(a,b)  (a)*(b)

这样才得到我们希望的结果s=(3+2)*(5+1)。

3. 如宏调用改为s=3/M(3+2,5+1),则替换后s=3/(3+2)*(5+1),                   也与

们希望的结果不符,这时应将宏定义改为

#define  M(a,b)  ((a)*(b))

这样才得到我们希望的结果s=3/((3+2)*(5+1))。通过以上两点是想让大家注意宏定义中圆括号的使用。

4. 宏定义中有双引号括起来的字符串常量中,含有形参,则在做宏替换时实参不能替换此双引号中的形参。如:          

#define  ADD(m)  printf(“m=%d/n”,m)

 用ADD(x+y);语句调用,结果为printf(“m=%d/n”,x+y);

 如要解决此问题则可在形参前加一“#”号,变为如下形式:

#define  ADD(m)  printf(#m“=%d/n”,m)

则调用ADD(x+y);语句后,结果就会变为printf(“x+y=%d/n”,x+y);

5. 如宏定义包含双“##”号,则宏替换时将双“##”号去掉,并将其前后字符串合在一起。例如:

#define  S(a,b)  a##b

当调用S(define ,5);语句时,宏展开为define5。