【C深入】20_宏定义与使用分析

宏定义常量:

#define宏定义常量可以出现在代码的任何地方

#define从本行开始,之后的代码都可以使用这个宏常量


以上宏定义都正确

最后一个宏定义采用了接续符“\”,等同于#define PATH_3  D:\Delphi\CTopic3.ppt


宏定义表达式

#define表达式有函数调用的假象,却不是函数

#define表达式可以比函数更强大

#define表达式比函数更容易出错

例1:

#define SUM(a,b)  (a)+(b)

printf("%d\n",SUM(1,2) * SUM(1,2));   //输出为5

本意是要求3*3=9,但是宏定义只是简单的替换,在预编译阶段宏展开后为printf("%d\n", (1)+(2)*(1)+(2));,所有输出为5,这时需要在宏定义表达式最外层加上括号为 #define SUM(a,b)  ((a)+(b)),这样宏展开后为printf("%d\n", ( (1)+(2))*((1)+(2)) );这样就可以输出想要的结果。

所以要搞定#define宏,不要吝啬括号。

例2:

#define MIN(a,b)  ( (a<b) ? (a) : (b) )

int min(int  a, int  b)

{

return  ( (a<b) ? (a) : (b) );

}

int i = 1, j = 5;

printf("%d\n",  MIN(i++, j));   //输出为2

printf("%d\n",  min(i++, j));   //输出为1

因为printf("%d\n",  MIN(i++, j))宏展开后是printf("%d\n",  ( (i++ < 5) ? (i++) : (5) )),i会自增两次,输出第二个i++的值就是2

而printf("%d\n",  min(i++, j))调用min函数,只是把i++和j的值即1和5的值穿进去了,所以输出还是1。

注意:宏函数被调用时是以实参代换形参,而不是“值传送”

例3:

#define DIM(array)  (sizeof(array) / sizeof(*array))

int dim(array[])

{

return sizeof(array) / sizeof(*array);

}

int a[] = {1,2,3,4,5};

printf("%d\n", dim(a));   //输出1  

printf("%d\n", DIM(a));   //输出5

C语言函数弱点,数组参数会退化为一个指针,所以函数dim(array[])中sizeof(array)就是指针所占用的空间大小,而不是数组所占用的空间大小

因此,此处宏定义DIM(array) 的功能远比函数要强大,没有任何一个函数能够实现这个宏的功能去检测一个数组里面有多少数组元素。


宏表达式与函数对比:

宏表达式在预编译期被处理,编译器不知道宏表达式的存在;

宏表达式用“实参”完全替代形参,不进行任何运算;

宏表达式没有任何的“调用”开销;

宏表达式中不能出现递归定义,如:

#define FAC(n)  ( (n>0) ? (FAC(n-1) + 1) : 0 ); 

printf("%d\n", FAC(20)); 

预编译宏展开后是printf("%d\n",  ( (20>0) ? (FAC(20-1) + 1) : 0 ));此时会认为FAC是函数,再经过编译后汇编代码中会出现call FAC语句,把FAC当函数了,随后汇编器汇编时就会报错,因为找不到FAC。


#undef:

宏定义的常量或表达式是否有作用域限制?

int f1(int a, int b)
{
    #define _MIN_(a,b) ((a)<(b) ? a : b)   
    return _MIN_(a, b);
}
int f2(int a, int b, int c)
{
    return _MIN_(_MIN_(a,b), c);
}

printf("%d\n", f1(2, 1));      //可以正常输出1
printf("%d\n", f2(5, 3, 2));  //输出2,说明函数f1里面的宏定义可以在函数f2中正常使用,如果函数f1最后再加一句#undef _MIN_(a, b);,f2中的宏就不起作用了。

所以,#define宏定义常量可以出现在代码的任何地方,#define宏的作用域从文件中的定义点开始,直到用#undef指令取消宏为止,或直到文件尾为止。


宏定义中的空格:

#define SUM    (x)   (x)+ (x) 
这还是定义的宏函数SUM(x)吗?显然不是。编译器认为这是定义了一个宏:SUM,其代表的是 (x)   (x)+ (x) 。为什么会这样呢?其关键问题还是在于SUM 后面的这个空格。所以在定义宏的时候一定要注意什么时候该用空格,什么时候不该用空格。这个空格仅仅在定义的时候有效,在使用这个宏函数的时候,空格会被编译器忽略掉。也就是说,定义好的宏函数SUM(x)的SUM和(x)之间不能有空格 ,在使用的时候在SUM 和(x)之间留有空格是没问题的。比如:SUM(3) 、SUM    (3)和SUM      (3)的意思是一样的。

猜你喜欢

转载自blog.csdn.net/zjy900507/article/details/80908212