【问题标题】:Break out of switch statement跳出 switch 语句
【发布时间】:2013-06-21 04:16:05
【问题描述】:

我总是要break出一个switch语句吗?简单地用分号; 退出是否不安全?

switch ( (rand() % 2) ) {
    case 0:
    // Do foo;
    break;
    case 1:
    // Do nothing
    ;
    default:
    ;
}

【问题讨论】:

    标签: objective-c c scope switch-statement break


    【解决方案1】:

    考虑Duff's Device(一个将N字节从内存中的一个位置复制到另一个位置的函数):

    send(to, from, count)
    register short *to, *from;
    register count;
    {
            register n = (count + 7) / 8;
            switch(count % 8) {
            case 0: do {    *to = *from++;
            case 7:         *to = *from++;
            case 6:         *to = *from++;
            case 5:         *to = *from++;
            case 4:         *to = *from++;
            case 3:         *to = *from++;
            case 2:         *to = *from++;
            case 1:         *to = *from++;
                    } while(--n > 0);
            }
    }
    

    它只有效——而且,是的,它确实有效——因为所有的案例都落到了下一个案例中,因为没有一个案例使用break;。所以,是的,您必须使用break; 退出case,但进入下一个case 可能很有用。

    不过,正如 Duff 的设备简明扼要地展示的那样,not 使用 break; 时会遇到一种明显的代码味道,对你自己来说太棘手了

    【讨论】:

    • 当然。我想知道您在“优化重构”、“效率”和“可读性”等目标之间划清界限。它确实闻起来 - 这就是我发布它的原因! :D
    • 另外,以 Duff 为例,在 Obj-C 中,他们是否更喜欢指针运算而不是 OOP?
    • @user2000809 在 ObjC 中,您通常会将任何棘手的 C 或 C++ 代码隔离在纯 C API 后面或封装在 ObjC 类中。指针算术和其他相对迟钝的 C 语言当然可以使用,它们的速度非常快,但是将它们隔离在 API 后面会使重构、测试和调试更容易。
    • 顺便说一句,原始设备使用*to 而不是*to++,因为它正在复制到具有特殊意义的特定位置(尽管我不知道/记得那是什么)。如果你想复制到一段普通内存中,你可以在每一行上使用*to++
    【解决方案2】:

    分号不会退出开关。否则每条语句(以分号结束)都会退出切换。

    如果不加break,就会执行下一个case。在您上面的情况下,它可能会像 default 一样工作,它是下一个并且它是空的,但通常您的代码会做意想不到的事情......

    【讨论】:

    • 这是一个比我更简洁准确的答案,但我一直想找个借口把 Duff 的设备扔到 SO...
    • @bbum 不错。很好地解释了如何(以及为什么不应该)使用不添加 break 的功能。
    • 是的,它不会“退出”开关,因为我打算让它通过并且什么也不做 - 所以这不会导致任何错误,因为switch 范围以括号结尾?
    • @user2000809 它不会导致错误,直到您返回添加案例 2:并忘记在案例 1 中插入中断;)我个人倾向于插入中断,除非您真的需要通过行为跌倒。如果真的需要失败,请认真想想你是否像 bbum 所说的那样,“对你自己的利益来说太棘手了”。
    • 并添加一个很好的评论来描述你在做什么,所以在 3 个月内你会记住什么是什么以及为什么......
    【解决方案3】:

    ; 不会阻止控件进入下一条语句。

    所以请始终将break;switch 一起使用,没有好的替代方案。

    ; 只是一个语句终止符。


    根据您的代码,

    case 1:
        // Do nothing
        ;
    

    如果您的案件与您无关,这确实不是必需的。你可以简单地省略它。

    【讨论】:

    • 没错,我可以省略供私人使用。为了完整起见,我与 cmets 一起留在原地,因此很明显,API 中的编码是经过深思熟虑的(而不是说,忘记了)
    【解决方案4】:

    switch 语句仅适用于常量并且需要中断是有原因的。 开关是用标签而不是条件实现的。

    switch (x){
       case 1: printf("1"); break;
       case 2: printf("2"); break;
    }
    

    相当于

    goto label_x; // where x is replaced with it's value
    label_1:
            printf("1");
            break;
    label_2:
            printf("2");
            break;
    

    这就是为什么在 C/C++ 中,如果你不设置中断,它只会继续到下一行代码(通过)。

    您应该在此处检查 C++ 控制结构: http://www.cplusplus.com/doc/tutorial/control/

    搜索“选择性结构:开关”

    【讨论】:

    • 还是不要使用gotogoto被认为是有害的
    • 我从不建议使用goto
    • Goto 是无害的,只是说而已。它只是破坏了代码的结构。因此,由于代码没有组织,因此更容易出错。它也有点违背结构化编程的意义。
    • 对。 goto = 顺序!= OOP。我的意思是对 Dijkstra 大喊“有害”:D
    猜你喜欢
    • 1970-01-01
    • 2010-12-31
    • 2014-08-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-29
    相关资源
    最近更新 更多