do...while(); 语句在宏定义中的应用。

首先声明一下do...while语句的原型:(注意最后位置需要一个分号,这个特性带来一些好处

do{
    /*循环体*/
}
while(condition);

如果你是C++程序员,我有理由相信你用过,或者接触过,至少听说过MFC, 在MFC的afx.h文件里面, 你会发现很多宏定义都是用了do…while(0)或do…while(false), 比如说:#define AFXASSUME(cond) do { bool __afx_condVal=!!(cond); ASSERT(__afx_condVal); __analysis_assume(__afx_condVal); } while(0) 
粗看我们就会觉得很奇怪,既然循环里面只执行了一次,我要这个看似多余的do…while(0)有什么意义呢? 

 

为什么需要使用do...whie(0),我们都知道do{...}while(condition)可以表示循环,但我们会遇见一些宏定义中可以不用循环的地方,使用到了do{...}while(0)。
ex1:

#define foo(x) do{\
    statement1;\
    statement2;\
}while(0)

#define foo(x) do{ statement1; statement2;}while(0)


在初次遇见这样的宏定义的过程中会觉得比较奇怪,既然循环里面的语句只执行了一次,为什么会需要看似多余的do...while(0)有什么意义。我们为什么不直接写出如下表达。
ex2:
#define foo(x)

    statement1;\
    statement2;\
}

#define foo(x){ statement1;statement2;}

ex3:(不带大括号,是错误的。)

#define foo(x)  statement1;statement2;


我们都知道宏在预处理的过程中会被直接展开

对于上面的ex2如果按照如下常规调用:

//调用语句

if(condition)
    Foo(x)
else
...

//展开语句
if(condition)
{
    statement1;
    statement2;
};
else
...

显然:else上面有一个分号是会报错的。VS中对else报错,提示“应输入一个语句”。

既然如此在调用的时候我不加上分号不就好了吗?答案是:这样的确是可以的。这样就变成了

//调用语句

if(condition)
    Foo(x)
else
...

//展开后的效果

if(condition)
{
    statement1;
    statement2;
}
else
...

只不过,这样不带分号不符合C语言的书写习惯,而且会给初学者一种错觉,应该避免才是。

然而采用ex1所示的宏定义就完全没有这种顾虑。因为如下:

//调用语句

if(condition)
    Foo(x);
else
...

//展开语句

if(condition)
do{
    statement1;
    statement2;
}while;
else

...

其实这种看起来的巧妙效果的实现非常简单。那就是do...while语句在while末尾处一定需要一个分号配对才可以。这样正好就把调用处的分号用于do...while语句的配对上了。既满足了do...while语句的语法需求,又在形式上保持了C语言调用语句出有一个分号的形式。

 

另外上述ex3形式是错误的,见如下例子:
#define Foo(x) (x)+=1;(x)+=1;

if(condition)
    Foo(x)
else
...
会被展开成
if(condition)
    (x)+=1;
    (x)+=1;
else
...
显然这样会被导致else语句孤立而出现编译错误。

 

见如下具体例子:

#include <iostream>
#include <string>
using namespace std;

#define Foo(x)  do{cout<<"hello";cout<<" world!";}while(0)
//#define Foo(x) cout<<"hello";cout<<" world!";


int main() {
	if (true == 1)
		Foo(2);
	else
		cout << "run else" << endl;

}

 


总结:通过do{...}while(0)我们使得宏能够被正确的展开,保留原始的语义,从而保证程序的正确性。

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

焱齿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值