为什么我不能“转到默认值”;或“转到案例x;”在开关选择结构内?

时间:2015-06-29 10:00:11

标签: c c99 c89 c11

Section 6.8.1 of C11C99C89的第3.6.1节似乎都表明defaultcase x(其中x是一些常量表达式)是标记语句的示例,旁边的identifier: - 样式标签适合与goto一起使用。

我知道我可以直接在identifier:default:标签后面添加case x:式标签。这不是这个问题的关键所在。我更加好奇是否有任何实际的理由背后禁止这种行为。

如果可以在default:选择结构之外声明switch标签,那么我会理解,因为goto内部switch之间会发生一些冲突1}}选择结构旨在瞄准。但是,section 6.4.1 of C11C99C89或3.1.1禁止将default用作关键字以外的任何内容,并且6.8.1将其使用限制为{{{ 1}}只有结构(或C11中的switch结构,这里不相关)。

我也理解,如果多个(可能是嵌套的)generic结构,每个都带有switch(或default:)标签引入歧义,但这些标签的范围似乎仅限于在它们最内部的case x:结构中,并且引用其范围之外的任何标识符显然是需要在编译时进行诊断的错误。

是否已在任何标准文件(例如理由)中讨论过这个问题?除了“因为它是”还是“因为规范是这样的”以外,对这种行为有什么解释吗?如果是这样,那是什么解释?

4 个答案:

答案 0 :(得分:7)

(我看不到goto case如何在句法上起作用。)

正如您所说,casedefault标签只有相应switch语句的范围,只能从外部跳转到。另一方面 C中的标签具有功能范围,可以从函数中的任何位置跳转到。

所以我们谈论的是具有完全不同属性的标签,它们可能在内部处理完全不同。协调这些属性似乎相对复杂,并且会使实现更复杂。突然之间,您必须决定何时实现goto casedefault是正确的.cover-image{ max-width: 300px; max-height: 250px; } ,而现在您只需要放置文件范围标识符的地址,那里。

所有这些都说,这只是对这种区别的原始意图的猜测。但我相信,沿着这些方向进行的论证很快就会扼杀任何引入此类功能的尝试。

答案 1 :(得分:7)

反例

fun() {
  switch (b) {
     case x:
       doSomething();
       break;
  }
  switch(b2) {
     case x:
       doMore();
       break;
  }

  goto x; // which one?
}

答案 2 :(得分:3)

  

ISO / IEC 9899:2011 信息技术 - 编程语言 - C

     

6.8.1标记语句

     
      
  1. 语法
  2.         
        

    标记的语句

             

    标识符:声明

             

    case constant-expression:statement

             

    默认:声明

      
         
        
    1. 案例或默认标签只应出现在switch语句中。在交换机下讨论了对这种标签的进一步限制   言。
    2.   
    3. 标签名称在功能中应是唯一的。
    4.   
    5. 任何语句前面都可以加上将标识符声明为标签名称的前缀。标签本身并没有改变   控制流程继续畅通无阻。
    6.         

      6.8.6跳转声明

           
          
      1. 语法
      2.         
            

        跳语句

                 

        转到标识符;

          
             

        6.8.6.1 goto语句

             
            
        1. goto语句中的标识符应命名位于封闭函数中某处的标签。
        2.   
        3. goto语句会导致无条件跳转到封闭函数中以命名标签为前缀的语句。
        4.         

          6.2.1标识符范围

               
              
          1. 标签名称是唯一一种具有功能范围的标识符。它可以在它出现的函数中的任何地方使用(在goto语句中),并通过其语法外观(后跟:和语句)隐式声明。
          2.   

casedefault标签不是标识符,名称标签

"因为规范是这么说的。"不要过度思考它。

答案 3 :(得分:1)

  

我知道我可以直接在identifier:default:标签后面添加case x:式标签。这不是这个问题的关键所在。我更加好奇是否有任何实际的理由背后禁止这种行为。

以听觉上的重言式为代价,理由是每个case旨在从一个goto(由switch语句创建的那个)唯一地跳转到。如果我们想要在多个条件的情况下执行代码块,那么我们还需要将更多案例标签组合在一起。

以下代码可能会给您一个直观的答案。如果允许goto [case label],那么为了转到第一个案例goto case 'q'goto case 'e',您会写些什么?哪一个是该代码块的老板

#include <stdio.h>

int yes_or_no (char input, char additional_yes) {

    int retval;

    switch (input) {

        case 'q':
        case 'e':

            printf("Bye bye! :-)\n");
            retval = 0;
            break;

        case 'n':

            printf("I am very sad that you said no :-(\n");
            retval = 0;
            break;

        case 'y':
        other_yes:

            printf("Thank you for saying yes! :-)\n");
            retval = 0;
            break;

        case '\n':
        case '\r':
        case ' ':
        case '\t':
        case '\v':
        case '\f':

            printf("Mmmmm... maybe you need time to think...\n");
            retval = 1;
            break;

        default:

            if (input == additional_yes) {

                goto other_yes;

            }

            printf("\"%c\" is not an answer!\n", input);
            retval = 1;


    }

    return retval;

}

int main (int argc, char *argv[]) {

    printf("Please, answer (yes/ja or no/nein) -- e or q to quit\n");

    while (yes_or_no(getchar(), 'j'));

    return 0;

}

另外考虑一下,在优化的过程中,如果编译器认为简单的重复if比切换更快,则可能决定不使用jump tables(尤其是{ {1}}标签不多)。在这种情况下,如果允许case,则会强制编译器创建一个通常没有标签的标签。

这是我最喜欢的C之一:如果你想要一些东西,你必须说出来。