原创作者: Arath   阅读:1606次   评论:0条   更新时间:2011-05-26    
在C中使用宏的确是一个非常好的代码手段,可以大量的减少代码量,提高阅读性,通过对一些常用代码的归类写成宏,作用巨大.
例如如下代码:

if(((t->flag & S_FLAG1) || (t->flay & S_FLAG2)) && t->type == T_TYPE1)

...
条件部分如果多次使用到,那么我们完全可以写如下的宏

#define IsXXXX(t) (((t->flag & S_FLAG1) || (t->flay & S_FLAG2)) && t->type == T_TYPE1)


这样上面的代码就成了

if(IsXXXX(t))
	...


代码少了很多,而且可读性也增加了很多。还有一个代码,C中分配一个结构,一般如下代码:

p=(STRUCT*)malloc(sizeof(STRUCT));


是否可以更加漂亮呢?创建一个宏,如下:

#define new(t)	(t*)malloc(t)


这样上面的代码就变成了

p=new(STRUCT);


是否有C++的风格了?

但是有利必有弊,宏一旦使用不当反而会产生严重的后遗症,下面随意说几点:

1.给宏赋予太强大的功能,几乎所有的编译器以及大部分的IDE无法展开和定位宏中的代码,所以一旦产生错误,很难调试, 如果真的需要最好还是用函数来封装.

2.宏名字起的不当,这是很致命的,会导致代码可读性大大降低,例如随意将前面例子中的IsXXXX定义为a,然后后面的代码中全是一堆的
if(a(t))。如果这样,键盘是少打了,但是已经完全没有了可读性,也许今天写的这个宏,明天你就忘记这个宏是做什么了. 同时过于简单的名字也会导致同名但是功能不同的宏大量出现,使得代码更难看懂.

3.宏的随意undef,这个是一个很不好的习惯,代码量一旦达到了一定程度,会导致极度的混乱.
例如在某个.h文件中定义了IsXXXX,然后在某个.c中如下使用
#undef IsXXXX
#define IsXXXX(t) (((t->flag & S_FLAG3) || (t->flay & S_FLAG4)) && t->type == T_TYPE2)

这个对于以后的维护修改埋下了极大的隐患.

4.重名,说起来这个算是很多编译器的问题,如果将一个宏的名字和一个变量的名字重名了,那么很多的C Compiler默认状态下不会报警或报错。例如:
int a;
...
#define a b

这种错误有时候简直可以让人发疯!!!

5.宏的嵌套使用,不是不能这么用,由于宏屏蔽了实际代码,如果宏->宏,那么即使你的宏写的够漂亮明了,恐怕天长日久也就忘记里面具体的逻辑,一旦想修改就很麻烦,所以要小心使用.
评论 共 0 条 请登录后发表评论

发表评论

您还没有登录,请您登录后再发表评论

文章信息

Global site tag (gtag.js) - Google Analytics