【问题标题】:switch : break without a caseswitch : 无案例中断
【发布时间】:2020-01-27 11:44:25
【问题描述】:

我有以下 switchbreak 没有 case

char c = 'a';
switch(c) {
    break;
    case 'a' : cout << 'a' << endl;
    break;
    case 'b' : cout << 'b' << endl;
    break;
    default : break;
}

为什么这段代码 sn-p 打印a?只在遇到第一个break 语句后,switch 不应该中断吗?

【问题讨论】:

  • switchbreak 不能这样工作(正如您所注意到的)。不在case 标签中的语句将被忽略。
  • 不,为什么?在 switch 中,一旦遇到适当的情况,您就输入代码。否则默认触发。为什么还要考虑这种无案例中断?当无大小写代码在 switch 中时,它应该是一个警告。
  • fwiw,我期待这可以通过阅读 en.cppreference.com/w/cpp/language/break 来回答,尽管在阅读之后仍然可以相信您的代码符合您的预期......

标签: c++ switch-statement


【解决方案1】:

第一个break 被忽略。

switch(c),运行时以c=='a' 跳转到case 'a'。之前的所有内容都会被忽略。

这就是为什么case 'b' 可以在不打印'a' 的情况下工作,这就是为什么在switch 块中不赞成变量定义:

int n=0;
switch (n)
{
    int k=n;
case 0:
    return k; // UB
}

【讨论】:

  • 它似乎格式不正确,而不是 UB。我得到error: cannot jump from switch statement to this case labelnote: jump bypasses variable initialization
  • @HolyBlackCat 我认为这是 UB,但所有主要编译器都足以引发错误;我没有看到在switch 块中提到具有不同生命周期的变量:eel.is/c++draft/stmt.switch
  • 另外,这里没有switcheel.is/c++draft/basic.lookup
  • 嗯。我问过a question
【解决方案2】:

在 C 中,switch 中的 case 是(类似于)goto 标签。 switch 的头部类似于 goto 本身。

后果

  • break 通常必须使用,因为“切换”是基于 goto 的,即不是结构化的或单点进入&退出
  • 永远不会到达第一个 case 之前的任何语句
  • 著名用法Duffs Device

【讨论】:

    【解决方案3】:

    switch 是一种紧凑且可读的形式,可能是一系列丑陋的 ifs 和 gotos,否则:

    char c = 'a';
    if(c=='a')goto _a;         // test for "case 'a':"
    if(c=='b')goto _b;         // test for "case 'b':"
    goto _default;             // unconditional jump to "default:"
    goto _break;               // <-- program never goes to this line, the one you are asking about
    _a: cout << 'a' << endl;
    goto _break;
    _b: cout << 'b' << endl;
    goto _break;
    _default:
    goto _break;
    _break:
    

    测试:https://ideone.com/OgsQuT

    【讨论】:

      【解决方案4】:

      来自cppreference

      如果条件的计算结果等于常量表达式之一的值,则控制权将转移到标有该常量表达式的语句。

      如果 condition 的计算结果与任何 case: 标签都不匹配,并且存在 default: label,则控制权将转移到使用 default: label 标记的语句。

      switch 的工作方式就好像从条件到cases 有一个goto,因此您的break 永远不会执行。更一般地说,你放在那里的任何东西都是死代码:

      switch(1) {
          foo();                // dead code !
          case 1 : cout << '1'; // prints "1"
               break;       // and exits the switch
          case 2 : cout << '2';
               break;
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-12-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-10-23
        • 1970-01-01
        相关资源
        最近更新 更多