do...while(0)的用法

1 篇文章 0 订阅

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;
}

向大佬们学习,奇技淫巧太好用啦! 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值