假设:
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
您可以通过简单的测试了解会发生什么:
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在执行发生的部分中设置了值.在这种情况下它起作用的事实并不是说它是推荐的做法.:)