#define _DIAGASSERT(x) do {} while (0)

#define _DIAGASSERT(x) do {} while (0) /* 在定义宏的时候如有必要(比方使用了if语句)就要使用do{…}while(0)将它封闭起来。 */

 

在刚开始阅读LINUX的时候有一个小小的宏让我百思不得其解:
#define   wait_event(wq,condition)   \
do{   \
if(condition)   \
                            break;   \
              __wait_event(wq,condition);   \
}while(0)
这是一个奇怪的循环,它根本就只会运行一次,为什么不去掉外面的do{..}while结构呢?我曾一度在心里把它叫做“怪圈”。原来这也是非常巧妙的技巧。在工程中可能经常会引起麻烦,而上面的定义能够保证这些麻烦不会出现。下面是解释:
假设有这样一个宏定义
#define   macro(condition)   \
if(condition)   dosomething();
现在在程序中这样使用这个宏:
if(temp)
              macro(i);
else
              doanotherthing();
一切看起来很正常,但是仔细想想。这个宏会展开成:
if(temp)
              if(condition)   dosomething();
else  
              doanotherthing();
这时的else不是与第一个if语句匹配,而是错误的与第二个if语句进行了匹配,编译通过了,但是运行的结果一定是错误的。
为了避免这个错误,我们使用do{….}while(0)   把它包裹起来,成为一个独立的语法单元,从而不会与上下文发生混淆。同时因为绝大多数的编译器都能够识别do{…}while(0)这种无用的循环并进行优化,所以使用这种方法也不会导致程序的性能降低。
正如微软声称的一样,宏定义与预编译器指令是强大的,但是它又使得程序难以调试。所以在定义宏的时候不要节省你的字符串,一定要力争完整的描述这个宏的功能。同时在定义宏的时候如有必要(比方使用了if语句)就要使用do{…}while(0)将它封闭起来。在宏定义的时候一定要注意各个宏之间的相互依赖关系,尽量避免这种依赖关系的存在。下面就有这样一个例子。
设有一个静态数组组成的整型队列,在定义中使用了这样的方法:
int   array[]={5,   6,   7,   8};
我们还需要在程序中遍历这个数组。通常的做法是使用一个宏定义
#define   ELE_NUM   4
…………………………..
……………………………..
for(int   I=0;I <ELE_NUM;I++)
{
              cout < <array[I];
}
由于某种偶然的原因,我们删除了定义中的一个元素,使它变成:
array[]={5,6,7}
而却忘了修改ELE_NUM的值。那么在上面的代码中马上就会发生访问异常,程序崩溃。然后是彻夜不眠的调试,最后发现问题出在这个宏定义上。解决这个问题的方法是不使用
array[]={….}这样的定义,而显式的申明数组的大小:
array[ELE_NUM]={….}
这样在改动数组定义的时候,我们就不会不记得去改宏定义了。总之,就是在使用宏定义的时候能够用宏定义的地方统统都用上。
我发现的另一个有趣的现象是这样的:
假设现在有一个课程管理系统,学生的人数用宏定义为
#define   STU_NUM   50
而老师的人数恰好也是50人,于是很多人把所有涉及到老师人数的地方通通用上STU_NUM这个宏。另一个学期过去,学生中的一个被开除了,系统需要改变。怎么办呢?简单的使用#define   STU_NUM   49   么?如果是这样,一个老师也就被开除了,我们不得不手工在程序中去找那些STU_NUM宏然后判断它是否是表示学生的数目,如果是,就把它改成49。天哪,这个宏定义制造的麻烦比使用它带来的方便还多。正确的方法应该是为老师的数目另外定义一个宏:
#define   TEA_NUM   50
当学生的数目改变以后只要把STU_NUM   定义为49就完成了系统的更改。所以,当程序中的两个量之间没有必然联系的时候一定不要用其中的一个宏去替代另一个,那只会让你的程序根本无法改动。
最后,建议C/C++语言的初学者尽可能多的在你的程序中使用宏定义和预编译指令。多看看MFC,ATL或者LINUX的源代码,你会发现C语言强大的原因所在。

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值