C语言的 Switch Case 的小问题

来源:互联网 发布:月相日历软件 编辑:程序博客网 时间:2024/05/29 05:57

 

一: 问题的提出

 

先上代码:

#include <stdio.h>    int main()  {      int a = 1;      while(a < 4)      {          switch(a)          {              int b = 20;          case 1:               //printf("XXXXX1\n");              int c = 5;              printf("b: %d\n",b);              printf("c: %d\n",c);              break;          case 2:              //printf("XXXXX2\n");              int d;              d = 6;              printf("b: %d\n",b);              printf("d: %d\n",d);                      default:              //printf("XXXXX3\n");              int e = 7;              printf("e: %d\n",e);              printf("b: %d\n",b);              break;          }          a++;      }         return 0;         } 

运行一下,我的gcc版本是:gcc version 3.4.620060404 (Red Hat 3.4.6-3)

结果如下所示:

[root@boss233 c_test]# gcc -o test switch_test.cswitch_test.c: In function `main':switch_test.c:13: error: syntax error before "int"switch_test.c:15: error: `c' undeclared (first use in this function)switch_test.c:15: error: (Each undeclared identifier is reported only onceswitch_test.c:15: error: for each function it appears in.)switch_test.c:19: error: syntax error before "int"switch_test.c:20: error: `d' undeclared (first use in this function)switch_test.c:25: error: syntax error before "int"switch_test.c:26: error: `e' undeclared (first use in this function)switch_test.c:10: warning: unreachable code at beginning of switch statement

显示的是c,d,e没有声明

那么去掉每个case里面的最前面printf语句前的注释符试试看:

[root@boss233 c_test]# gcc -o test switch_test.cswitch_test.c: In function `main':switch_test.c:10: warning: unreachable code at beginning of switch statement

得到的结果是: 跟上一个编译结果的最后一行一样,出现了一个warning:

先来试试看运行结果吧:

[root@boss233 c_test]# ./testXXXXX1b: 0c: 5XXXXX2b: 0d: 6XXXXX3e: 7b: 0XXXXX3e: 7b: 0

 

1.  首先是发现b的值是不对的。

2.  c,d,e是对的。


下面便来解释这两个问题。

二、第一个问题


第一个问题可以参考下:

http://blog.csdn.net/tonywearme/article/details/7075809

在执行到switch的时候,便根据switch所要的标识,找到对应的case,是一个jmp的过程(goto语句也是jmp的过程).

因而在jump的时候跳过了switch和case之间的部分。所以b只是声明了,而没有初始化。

所以b的值也不一定就是这里打印的“1”,也有可能是个其他的随机值。

 

这篇文章还分析了一些作用域的问题,在此不再赘述了。


三、第二个问题

 

这个问题可以理解成: 紧接着case语句之后初始化变量是编译不过去的,但是在执行一些语句之后,就可以编译过去了。

 

原因不清楚,应该是编译器实现的原因吧。

在我的机器上用g++编译这段代码, 或者用vs 编译,即便是在case后面printf语句并没有注释,也编译不过去。

[root@boss233 c_test]# g++ -o test switch_test.cswitch_test.c: In function `int main()':switch_test.c:11: error: jump to case labelswitch_test.c:10: error:   crosses initialization of `int b'switch_test.c:17: error: jump to case labelswitch_test.c:13: error:   crosses initialization of `int c'switch_test.c:10: error:   crosses initialization of `int b'switch_test.c:23: error: jump to case labelswitch_test.c:13: error:   crosses initialization of `int c'switch_test.c:10: error:   crosses initialization of `int b'switch_test.c:10: warning: unreachable code at beginning of switch statement

但是正如上面文章所讲的那样: 在case中用{}形成一个局部作用域,编译的结果如下:
[root@boss233 c_test]# g++ -o test switch_test.cswitch_test.c: In function `int main()':switch_test.c:11: error: jump to case labelswitch_test.c:10: error:   crosses initialization of `int b'switch_test.c:17: error: jump to case labelswitch_test.c:10: error:   crosses initialization of `int b'switch_test.c:23: error: jump to case labelswitch_test.c:10: error:   crosses initialization of `int b'switch_test.c:10: warning: unreachable code at beginning of switch statement

可以看到b仍然是不能执行的,显示的是“跳过了 b的初始化”。

把b定义的那行去掉,并去掉case里面的b的打印语句。便能编译成功、正确运行。

 

那么加入 {} 形成局部作用域之后,gcc能否正确编译和运行呢? 是的。即便不加 case后面紧跟着的case语句。

最终的程序是:

#include <stdio.h>int main(){int a = 1;while(a < 4){ switch(a) {case 1: {int c = 5;printf("c: %d\n",c);break;}case 2:{int d;d = 6;printf("d: %d\n",d);break;}default:{int e = 7;printf("e: %d\n",e);break;}}a++;}return 0;}

运行结果:

[root@boss233 c_test]# g++ -o test switch_test.c[root@boss233 c_test]# ./testc: 5d: 6e: 7[root@boss233 c_test]# [root@boss233 c_test]# gcc -o test switch_test.c[root@boss233 c_test]# ./testc: 5d: 6e: 7

但是上面解释的都是通过给case语句添加 {} 形成一个局部作用域来解决问题,并没能解释case语句之后紧跟着一些执行语句(比如printf这种不需要初始化的语句),之后便能够进行初始化的问题。难道是这样也形成了局部作用域(感觉很不对)?


但类似的问题,在实验室的一个硬件平台上给case加上{} 也无能为力,但是在case和初始化之间加入一些执行语句倒是可以通过并运行的。这个平台上面采用的是厂商自己的编译器,应该是对gcc进行修改后得到的吧。

这样的一段C代码比较tricky:

switch (something){  case 1:; // Ugly hack empty statement    int i = 6;    do_stuff_with_i(i);    break;  case 2:    do_something();    break;  default:    get_a_life();}


大家有兴趣就试试看吧。

这个问题,个中原因我也不是很清楚。 还希望大家指教。