我可以将代码放在案例之外的交换机中吗?

Pet*_*ter 9 c c++

假设:

switch ( test ) {

  // Set some variables, call some functions ?
  int x = 1 ;
  int y = function(x) ;
  //

  case 1 : 
    // Process for test = 1
    ...
    break;

  case 5 : 
    // Process for test = 5
    ...
    break;

  default : 
    // Process for all other cases.
    ...

}
Run Code Online (Sandbox Code Playgroud)

执行我在第一个之前添加的额外代码是"合法的" case吗?我在例子中从未见过这个.

Ulf*_*zer 12

首先介绍一下如何switch(真的)有效:

A switch通常被认为是一个构造,它根据某个表达式的值选择要执行的代码片段,如

switch (x) {
case 1:
    foo();
    break;

case 2:
    bar();
    break;
}
Run Code Online (Sandbox Code Playgroud)

但是,将a switch视为一种计算goto语句更为准确.例如,以下内容完全合法:

switch (x) {
    puts("I can't be reached");
case 1:
    if (cond) {
case 2:
        puts("Either x == 1 && cond, or x == 2");
    }
}
Run Code Online (Sandbox Code Playgroud)

根据值x,程序将跳转到case 1或case 2(或者过去的switchif x既不是1也不是2).


您的程序将编译为C(由于跳过初始化x,因此y在其中和内部具有垃圾值switch),但不是C++.原因是C++不允许跳转到case标签来跨越变量的初始化.对于简单类型int,int x;允许跳过(因为不涉及初始化),但不跳过int x = 1;.

这种差异的主要动机可能是,case当涉及构造函数时,跳转到C++初始化的标签是不安全的.例如,如果C++允许在某个范围内case的定义之后发生标签My_class my_object,那么跳转到该case标签将跳过my_object构造函数,但在退出范围时仍然运行其析构函数.

同样的限制适用goto于C++.您无法使用它跳转到块并通过变量初始化.


作为一个侧面说明,switch遵循相同的一般语法if和while.ifC11标准(ISO/IEC 9899:2011,第6.8.4节)中给出的语法是

if(表达式)语句

,而语法switch是

switch(表达式)语句

关于语句的唯一区别(在C - C++中增加了一些如上所述的限制)是允许它包含case标签(和break)switch但不包含if(除非if发生在a中switch).

就像使用a一样if,您甚至可以省去大括号并编写如下代码.(这是否会造成不必要的混淆是另一种讨论.)

switch (x) case 1: case 2: puts("x is 1 or 2");
Run Code Online (Sandbox Code Playgroud)

在语法上,标签case与default标签属于同一类别goto.C11标准的第6.8.1节有以下定义:

labeled-statement:
        identifier : statement
        case constant-expression : statement
        default : statement

  • 也许吧,但是你必须要对你的老板表示不满,同事把东西放在你的咖啡里......这不是一个好的情况. (4认同)
  • 我真诚地希望我从来没有遇到像最后那样的转换声明. (2认同)
  • @Qix:可能会作为一种策略来使你的代码足够神秘,但你不能被解雇.:) (2认同)

lur*_*ker 7

您可以通过简单的测试了解会发生什么:

int w = 1;

switch (w)
{
    int i = 3;
    int y = foo(i);

case 1:
    printf("here %d\n", y);
    printf("here %d\n", i);
    break;

case 2:
    printf("not here\n");
    break;
}
Run Code Online (Sandbox Code Playgroud)

这段代码将在函数内部编译使用gcc.C编译器在由大括号分隔的块内查看i并y声明,因此将接受它.不过,printf声明将打印垃圾的i和y,因为分配是永远不会被执行.这是因为一个switch语句形成一个跳转到case对应于头部的表达式switch.因此case无法到达左大括号和第一个大括号之间的可执行代码.请参阅为什么不能在switch语句中声明变量?,它没有解释完全相同的情况,但确实有一些关于该switch声明的相关讨论.

如果你在打开警告(gcc -Wall)的情况下编译它,你得到:

foo.c: In function ‘main’:
foo.c:19:15: warning: ‘y’ may be used uninitialized in this function [-Wuninitialized]
foo.c:20:15: warning: ‘i’ may be used uninitialized in this function [-Wuninitialized]
Run Code Online (Sandbox Code Playgroud)

有趣的是,以下代码将编译而没有警告和工作:

int w = 1;

switch (w)
{
    int i;
    int y;

case 1:
    i = 2; y = 3 * i;
    printf("here %d\n", y);
    printf("here %d\n", i);
    break;

case 2:
    i = 1; y = 2;
    printf("here %d\n", y);
    printf("here %d\n", i);
    break;
}
Run Code Online (Sandbox Code Playgroud)

变量按照您的预期打印,因为它们是在switch块的范围内声明的,并且case在执行发生的部分中设置了值.在这种情况下它起作用的事实并不是说它是推荐的做法.:)