概述
1:定义复杂宏并避免编译错误
当你定义了一个这样的宏
#define fun() fun1(); fun2()
代码被翻译前后的样子
// 翻译前
fun();
// 翻译后
fun1();
fun2();
这是没有什么问题的,但是当加上if条件判断后,情况就发生了一些微妙的变化
// 翻以前
if (condition == TRUE)
fun();
// 翻译后
if (condition == FALSE)
fun1();
fun2();
可以看到,逻辑已经发生了变化,不是我们期望的执行逻辑了。
那如果给宏加上“{}”是不是就可以呢?
#define fun() { fun1(); fun2(); }
1:
// 翻译前
if (condition == TRUE)
fun();
//翻译后
if (condition == TTRUE) {
fun1();
fun2();
};
2:
// 翻译前
if (condition == TRUE)
fun();
else
other();
//翻译后
if (condition == TTRUE) {
fun1();
fun2();
};
else
other();
可以看到多了一个冒号,已经发生了编译错误。
但是如果给宏加上do...while(0),以上所有问题都将迎刃而解:
#define fun() do { fun1(); fun2(); } while(0)
1:
// 翻译前
if (condition == TRUE)
fun();
//翻译后
if (condition == TTRUE)
do {
fun1();
fun2();
} while(0);
2:
// 翻译前
if (condition == TRUE)
fun();
else
other();
//翻译后
if (condition == TTRUE)
do {
fun1();
fun2();
} while(0);
else
other();
借用大佬们的一句话进行总结:Linux和其它代码库里的宏都用do/while(0)来包围执行逻辑,因为它能确保宏的行为总是相同的,而不管在调用代码中使用了多少分号和大括号。
2:代替goto实现更可控的跳转
当我们在C/C++中处理一段重要的逻辑的时候,有时候总是会出现这样那样的意外情况,此时就需要我们有一个兜底方案来处理意外来临时的烂摊子,比如置空对象、回收内存等,如果用goto来实现,将会是这个样子:
void* execute() {
int *p_int = new int;
void *ptr = malloc(1024);
int ok = fun0(ptr);
if (!ok) {
goto errorhandle;
}
ok = fun1(ptr);
if (!ok) {
goto errorhandle;
}
ok = fun2(ptr);
if (!ok) {
goto errorhandle;
}
delete p;
p = nullptr;
return ptr;
errorhandle:
delete p;
p = nullptr;
free(ptr);
return nullptr;
}
goto语句太多,虽然goto可增加灵活性,但是代码读起来很恶心,同时执行起来也很危险。如果用do...while(0)来做一些改变,将会是这样:
void* execute() {
int *p_int = new int;
void *ptr = malloc(1024);
do {
int ok = fun0(ptr);
if (!ok) {
break;
}
ok = fun1(ptr);
if (!ok) {
break;
}
ok = fun2(ptr);
if (!ok) {
break;
}
delete p;
p = nullptr;
return ptr;
} while(0);
delete p;
p = nullptr;
free(ptr);
return nullptr;
}
向大佬们学习,奇技淫巧太好用啦!
最后
以上就是真实小蚂蚁为你收集整理的do...while(0)的用法的全部内容,希望文章能够帮你解决do...while(0)的用法所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复