美文网首页
iOS中do{}while(0)的使用

iOS中do{}while(0)的使用

作者: 小盟城主 | 来源:发表于2019-01-10 18:23 被阅读32次

  do while循环是执行一遍do{}里面的代码,然后再去while(条件)判断条件是否为真,为真继续执行do{}里面的代码,否则就跳出循环。当然我们也可以采用break跳出循环,也可以采用continue结束本次循环开始下一次循环。

do {
    //执行的任务
} while (条件); //判断条件是否为真

  经常发现有人写do{}while(0)这样的代码,初看时让人迷惑不解,按照上面的语法do{}while(0)这样do{}里面的代码只会执行一次,那么这段代码又有什么意义呢?

一、简化if else的嵌套结构判断逻辑

  我们在工作中是不是经常会遇到一种情况:第二个判断需要依赖第一个判断的结果,甚至第三个判断需要依赖第二个判断的结果。如下样式的代码:

if (one == true) {

    if (two == true) {

        if (three == true) {
            //第三个依赖第二个判断结果,第二个依赖第一个判断结果。
            //...
        }
    }
}

  上面的代码各种判断嵌套在一起,不容易理清代码逻辑,而且很容易出错。这个时候就可以do{}while(0)来简化代码。

do {
    if (one == false) {
        break;
    }
    if (two == false) {
        break;
    }
    if (three == false) {
        break;
    }
} while (0);

  既然后面的判断依赖前面的判断结果,那么所有的条件都去判断是否等于false,等于false的直接break跳出do while循环。这样的代码风格就简化很多了。

二、辅助定义复杂的宏,避免引用的时候出错

假设你需要定义这样一个宏:

#define swap(a,b)    {int t=a;a=b;b=t;}

上面的宏在下面使用中是不会出现问题的:

- (void)viewDidLoad {
    [super viewDidLoad];
    int x = 1, y = 2;
    swap(x, y);
    NSLog(@"%d %d", x, y);
}

但是,如果这个宏出现在if else语句中

- (void)viewDidLoad {
    [super viewDidLoad];
    int x = 1, y = 2,z = 3;
    if (x > y)
        swap(x, y);
    else
        swap(y, z);
    NSLog(@"%d %d %d", x, y, z);
}

上面的代码是无法正常编译通过的。为什么?很简单,加入编译器将swap这个宏替换为最终的代码,那么,就是这样:

- (void)viewDidLoad {
    [super viewDidLoad];
    int x = 1, y = 2,z = 3;
    if (x > y)
    {
        int t=a;
        a=b;
        b=t;
    };  //这里多了分号会运行到这里面就结束了 后面else会出现问题
    else
        swap(y, z);
    NSLog(@"%d %d %d", x, y, z);
}

注意花括号后面的那个分号,这使得编译器认为if就这样结束了,而后面的else也就没有与之匹配的if了。
这不是我们想要的结果。如果我们在使用swap宏的时候不在后面加上分号不就行了吗?像这样:

if (x > y)
        swap(x, y)
    else
        swap(y, z);

注意第一个swap,后面没有加上分号,这样确实编译的错误也就没有了,但是,这也不是一个好主意,毕竟在代码中突然冒出来一句末尾没有分号的语句会让人感到很奇怪,而且这不利于代码的维护(使用这个宏的人都得注意这个宏存在的问题,就是末尾不要加分号才能保证不出错)

如此,便有了题目所示的方法,使用do{}while(0)将宏的内容包围起来,一来能够起到和大括号同样的效果(里面的临时变量不会影响调用方的变量,试想你的宏里面有个变量t,你也在调用宏的地方有一个变量t,是否冲突?);二来也可以避免在if里面作为单个语句使用,不给if加花括号的时候会出现问题,无法通过编译(当然,如果你有在if后面加大括号的习惯,这个问题还是可以避免的,不过不能保证其它场合不会出现问题)。不多说,就像代码写的这样:

#define swap(a,b)   do {int t=a;a=b;b=t;} while(0)
- (void)viewDidLoad {
    [super viewDidLoad];
    int x = 1, y = 2,z = 3;
    if (x > y)
        swap(x, y);
    else
        swap(y, z);
    NSLog(@"%d %d %d", x, y, z);
}

在宏的前后分别使用dowhile(0)围起来(尾部没有分号),这样,我们就可以直接在if下面使用也不会出现问题了。这样定义宏,它才真正能够被看做一个单独的表达式使用,加上末尾分号才真正等价于一条单独的语句。

相关文章

网友评论

      本文标题:iOS中do{}while(0)的使用

      本文链接:https://www.haomeiwen.com/subject/epearqtx.html