C语言的 Switch Case 的小问题

 

一: 问题的提出

 

先上代码:

#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没有声明

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

[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();
}


大家有兴趣就试试看吧。

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










  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值