【问题标题】:switch-case statement without break无中断的 switch-case 语句
【发布时间】:2016-01-18 06:33:57
【问题描述】:

根据我正在阅读的这本书:

Q 如果我在 switch-case 语句中省略了 break 会发生什么?

A break 语句使程序执行能够退出 switch 构造。 没有它,执行将继续评估以下 case 语句。

假设我的代码看起来像

switch (option}{
    case 1:
    do A;
    case 2:
    do B;
    default:
    do C;
    break;
}

这是否意味着如果我选择案例 1,A 和 C 就完成了。如果我选择案例 2,B 和 C 就完成了。如果我都不选择,那么只有 C 完成。

如果是这样,如果我们在 do C 之后省略了 break 会发生什么。

我认为这些都是不好的编程习惯,但我很好奇会发生什么来更深入地了解它是如何工作的。谢谢

【问题讨论】:

  • “如果我选择案例1,A和C都完成了”:没有A,B和C完成。
  • 只需编译一些执行此操作的测试代码,您就会发现:p
  • 您从所选案例开始执行一切,直到看到breakswitch 语句结束。所以可能只有 C 被执行,或者 B 然后 C,或者 A 和 B 和 C,但从来没有 A 和 C。
  • 顺便说一句,这是一个不错的编程习惯。
  • 强制引用Duff's Device :)

标签: c++ switch-statement


【解决方案1】:

如果没有 break 语句,每次在 switch 中发生匹配时,该 case 和 SUBSEQUENT CASES 的语句都会执行,直到遇到 break 语句或 switch 结束。

【讨论】:

    【解决方案2】:

    自己试试 - 使用 ideone 运行代码here

    #include <stdio.h>
    
    void doA(int *i){
        printf("doA i = %d\n", *i);
        *i = 3;
    }
    
    void doB(int *i){
        printf("doB i = %d\n", *i);
        *i = 4;
    }
    
    void doC(int *i){
        printf("doC i = %d\n", *i);
        *i = 5;
    }
    
    int main(void) {
        int i = 1;
        switch(i){
            case 1:
                doA(&i);
            case 2:
                doB(&i);
            default:
                doC(&i);
                break;
        }
        return 0;
    }
    

    输出:

    doA i = 1
    doB i = 3
    doC i = 4
    

    注意:

    • 它将执行所选案例中的所有选项,直到看到breakswitch 语句结束。所以可能只有 C 被执行,或者 B 然后 C,或者 A 和 B 和 C,但从来没有 A 和 C
    • 如果您更改句柄函数内 switch 中分析的变量的值(例如 doA),则不会影响上述流程

    【讨论】:

      【解决方案3】:

      break 的作用类似于goto 命令。或者,作为一个更好的例子,就像在 void 函数中使用 return 时一样。既然到了最后,有没有没有关系。不过,我确实喜欢包含它。

      【讨论】:

      • 在 cmets 留在问题下方后,我怀疑这一点。这是一个很好的解释,谢谢。
      • 嗯,我认为强调 GOTO 类似 break 的性质很重要。
      • @Kyle Strand 我在想它可能更好地描述为由于范围而在 void 函数中返回。
      • @craigmosey 嗯,我想我的意思是重要的是要意识到switch 本身就像GOTO,因为个人cases 不是 i> 单独的范围(除非您明确添加范围)。因此,与函数不同的是,在进入/退出 case没有自动设置或清理。
      • 如果接受的答案涵盖了 OP 的所有方面,那就太好了。特别是需要编辑指出,在情况1中,A、B、C都将被执行,而不仅仅是A和C。
      【解决方案4】:

      关键是将执行控制转移到匹配案例的语句中。 例如

      1. switch(x) {
      2.   case 1:
      3.      do_step1;
      4.   case 2:
      5.      do_step2;
      6.   default:
      7.      do_default;
      8.   }
      

      将第 2、4、6 行视为 goto 调用的“标签”。在 x = 1 时,控制权将转移到第 3 行并执行第 3、5 和 7 行。

      【讨论】:

      • "goto calls" 很好的思考方式。我学到了一些新东西。谢谢
      【解决方案5】:
      switch (option}{
          case 1:
          do A;
          case 2:
          do B;
          case 2:
          do C;
          break;  
          default:
          do C;
      }
      

      如果您的选项是1,它将执行所有操作,直到找到break 关键字... 这意味着 break 结束 switch 的执行 --> case 输出:A 然后 B 然后 C 所以建议在每个案例之后放一个break 喜欢:

      switch (option}{
              case 1:
              do A;
              break;
              case 2:
              do B;
              break;
              do C;
              break;        
              default:
              do D;
          }
      

      如果您的选项是 1,则输出将是:just A ...

      注意:default 不需要break

      【讨论】:

        【解决方案6】:

        我在许多 cmets 和答案中看到省略 break 行是一种不好的做法。我个人觉得在某些情况下它非常有用。

        让我们举一个非常简单的例子。这可能不是最好的,仅作为说明:
        - 登录失败时,您需要记录失败的尝试。
        - 对于第三次错误尝试,您想要登录并做一些进一步的事情(提醒管理员,阻止帐户,...)。

        由于第一次和第二次尝试的操作相同,因此无需在这两者之间break 并再次重写相同的命令。
        现在第三次,您想做其他事情并记录。只是先做其他事情,然后通过第一次和第二次尝试的日志操作让它运行(没有break):

        switch (badCount) {
            case 3: //only for 3
                alertAdmin();
                blockAccount();
            case 2: //for 2 AND 3
            case 1: //for 1 AND 2 and 3
                errorLog();
                badCount++;
        }
        

        恕我直言,如果在不同情况下使用通用代码是一种非常糟糕的做法,那么 C 结构将根本不允许这样做。

        【讨论】:

        • 你应该使用 if 语句,而不是 switch。开关应该是叠加表达式值的不相关情况,没有人阅读您的代码会发现代码的垂直方向与其逻辑方向相对应。
        • 那你的意思是没有人能够阅读和理解微软在线文档中的基本示例? docs.microsoft.com/en/cpp/c-language/…,参见示例代码块 2 和 4。
        【解决方案7】:
        • 如果在任何情况下都没有包含 break,那么下面的所有情况都将被执行,直到它看到 break。

        • 如果您在默认值中不包含中断,则它不会产生任何影响,因为在此“默认”情况下没有任何情况。

        • 不使用 break 通常被认为是一种不好的做法,但有时它也可能会派上用场,因为它具有穿透性。例如:

          案例选项A:

          //optionA needs to do its own thing, and also B's thing.
          //Fall-through to optionB afterwards.
          //Its behaviour is a superset of B's.
          

          案例选项B:

          // optionB needs to do its own thing
          // Its behaviour is a subset of A's.
          break;
          

          案例选项C:

          // optionC is quite independent so it does its own thing.
          break;
          

        【讨论】:

          【解决方案8】:

          从所选案例开始执行所有操作,直到看到breakswitch 语句结束。所以可能只有C被执行,或者B然后C,或者A和B和C,但从来没有A和C

          【讨论】:

            最近更新 更多