一: 问题的提出
先上代码:
#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.c
switch_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 once
switch_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没有声明
[root@boss233 c_test]# gcc -o test switch_test.c
switch_test.c: In function `main':
switch_test.c:10: warning: unreachable code at beginning of switch statement
得到的结果是: 跟上一个编译结果的最后一行一样,出现了一个warning:
先来试试看运行结果吧:
[root@boss233 c_test]# ./test
XXXXX1
b: 0
c: 5
XXXXX2
b: 0
d: 6
XXXXX3
e: 7
b: 0
XXXXX3
e: 7
b: 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.c
switch_test.c: In function `int main()':
switch_test.c:11: error: jump to case label
switch_test.c:10: error: crosses initialization of `int b'
switch_test.c:17: error: jump to case label
switch_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 label
switch_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.c
switch_test.c: In function `int main()':
switch_test.c:11: error: jump to case label
switch_test.c:10: error: crosses initialization of `int b'
switch_test.c:17: error: jump to case label
switch_test.c:10: error: crosses initialization of `int b'
switch_test.c:23: error: jump to case label
switch_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]# ./test
c: 5
d: 6
e: 7
[root@boss233 c_test]#
[root@boss233 c_test]# gcc -o test switch_test.c
[root@boss233 c_test]# ./test
c: 5
d: 6
e: 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();
}
这个问题,个中原因我也不是很清楚。 还希望大家指教。