关于case语句中的变量声明,定义语句

todototry 2006-12-12 09:23:07
希望高手指点
switch(ch)
{
case'a':
int a = 0;
break;
case'b':
cout << "ok" << endl;
break;
}
编译会报错,
小弟理解如此:在一个case语句中的变量声明,定义在整个switch语句可见,但是对于case‘b’分支执行的时候,只能a的声明可见,而a定义语句由于case‘a’未执行,所以这没找到,所以报错,是这样的么?
如果是的话,a的定义实在运行时根据执行哪个分支才去查找的么,为什么不是编译的时候?
或者都不恰当,希望高手指教,谢谢各位大哥!
...全文
839 17 打赏 收藏 转发到动态 举报
写回复
用AI写文章
17 条回复
切换为时间正序
请发表友善的回复…
发表回复
HappyTree 2006-12-12
  • 打赏
  • 举报
回复
学习了!
todototry 2006-12-12
  • 打赏
  • 举报
回复
谢谢高手指教
hitranbor 2006-12-12
  • 打赏
  • 举报
回复
看C++primer就知道细节了,不多讲了。

要在语句块中声明,比如:
case'a':
{
int a = 0;
break;
}

仅仅加一个括号就可以编译通过。
OOPhaisky 2006-12-12
  • 打赏
  • 举报
回复
再解释一遍(就10分,太少了^_^)。

switch(ch)
{
case'a':
int a = 0;
//break;将break去掉,便于说明
case'b':
cout << "ok" << endl;
break;
}
这个是错误的,编译器不会让他通过编译,理由是这样的:
"int a = 0"这个定义放在了case 'a'中,如果允许它顺利通过编译,会造成“不一致”,考虑西面两种情况:
1.ch='a':执行case 'a'分支,a顺利的被初始化为0,执行完case'a'之后,会顺序执行case'b'(因为我把break注释掉了),此时如果在case'b'中引用了a,是没有任何问题的。
2.ch='b':直接执行case'b'分支,由于跳过了case'a'分支,所以a并没有被初始化为0,但是a在case'b'中仍然可见(即case'b'中仍然可以引用a),那么如果在case'b'中引用了a,则出现了问题,因为现在a是“未初始化的”。
好了,说到这里,楼主应该清楚为什么编译器禁止上述写法了吧!

现在我们再来看看下面这种:
switch(ch)
{
case'a':
{int a = 0;}
//break;将break去掉,便于说明
case'b':
cout << "ok" << endl;
break;
}
这个可以通过编译,因为此时在case'b'中a不可见(因为a在语句快中),所以不会出现上述的“不一致”现象,因此编译顺利通过。

再来看看下面的情况:
switch(ch)
{
case'a':
...
//break;将break去掉,便于说明
case'b':
int a = 0;
break;
}
此时也会顺利通过编译,因为a的定义(初始化)放在了最后一个分支中,由于在case'b'后面没有其他分支了,所以同样不会出现上述的“不一致”现象,所以仍然顺利通过编译。(ps:但是个人仍然不太喜欢这种用法)

回答完毕^_^
OOPhaisky 2006-12-12
  • 打赏
  • 举报
回复
老问题了,以前给别人解答过。
missilery 2006-12-12
  • 打赏
  • 举报
回复
case X:
{
...
break;
}
blue_zyb 2006-12-12
  • 打赏
  • 举报
回复
去掉初始化后,也可以在case 'b'中访问a变量,例如下面的代码:

int main()
{
char ch = 'b';
switch(ch)
{
case'a':
int a; // 将int a = 10;改为int a;
break;
case'b':
a = 10;
cout << "a is modified by case \'b\' to the value of " << a << endl;
break;
}

return 0;
}

上面的代码将输出
a is modified by case 'b' to the value of 10

这也说明了"在一个case语句中的变量声明,定义在整个switch语句可见"


PS:刚拷贝的时候发现lz用的是“在一个case语句中的变量声明,定义在整个switch语句可见”,用的是“声明,定义”,是没有错的。我上一贴改的“定义”反而不好,因为漏掉了声明的情形,例如:

int a = 1;

int main()
{
char ch = 'b';
switch(ch)
{
case'a':
extern int a;  // this is declaration
break;
case'b':
cout << "originally a is " << a << endl;
a = 10;
cout << "a is modified by case \'b\' to the value of " << a << endl;
break;
}

return 0;
}
将输出:
originally a is 1
a is modified by case 'b' to the value of 10
blue_zyb 2006-12-12
  • 打赏
  • 举报
回复
小弟理解如此:在一个case语句中的变量声明,定义在整个switch语句可见,但是对于case‘b’分支执行的时候,只能a的声明可见,而a定义语句由于case‘a’未执行,所以这没找到,所以报错,是这样的么?
-----------------------------
首先,lz对于对于变量声明和定义的理解似乎有点问题。对于int a;也是定义,也就是说编译器将为a分配存储,这在编译时被处理。而int a = 0;是定义+初始化,定义的分配存储的action在编译时完成,初始化的action则在运行时完成(将执行类似dword ptr [ebp-4],0的指令,而单独的int a;不会有对应的执行指令)


在一个case语句中的变量声明,定义在整个switch语句可见
---------------------------------------------------
这一句的理解倒是正确,但把声明改为定义似乎更为恰当。


那么,我们可以看一下VC对于这种情形的报错信息:
error C2360: initialization of 'a' is skipped by 'case' label

是说a的初始化的action被skip掉了,也就是说,如果ch的值为'b',control直接跳到了case 'b'对应的语句,而把只有在case 'a'中才可能执行的初始化指令skip掉了。但是如果不是初始化,而只是单独的定义,就不会出错:
switch(ch)
{
case'a':
int a; // 将int a = 10;改为int a;
break;
case'b':
cout << "ok" << endl;
break;
}





taodm 2006-12-12
  • 打赏
  • 举报
回复
C、C++标准没有明确说明理由的东西,你怎么找也不算理论支持。不要太钻牛角尖。
todototry 2006-12-12
  • 打赏
  • 举报
回复
每个人的理解未必要相同,只要你自己觉得可以解释所有情况,能自圆其说即可。
====================================

这个能,呵呵
想有理论支持
taodm 2006-12-12
  • 打赏
  • 举报
回复
每个人的理解未必要相同,只要你自己觉得可以解释所有情况,能自圆其说即可。
todototry 2006-12-12
  • 打赏
  • 举报
回复
case内不可以直接定义变量。这是规定。
想想,如果不是int a;
而是 class Test t;编译器要怎么安排构造、析构函数的调用?
============================
对,我知道是规定,但是它这么规定的目的是什么,为了避免什么情况
我的理解对么,谢谢taodm兄,指教
todototry 2006-12-12
  • 打赏
  • 举报
回复
第一、楼主请检查你的代码
第二、case也算是语句作用域
=============
感觉说得有些不太对题
taodm 2006-12-12
  • 打赏
  • 举报
回复
case内不可以直接定义变量。这是规定。
想想,如果不是int a;
而是 class Test t;编译器要怎么安排构造、析构函数的调用?
todototry 2006-12-12
  • 打赏
  • 举报
回复
case'a':
{int a = 0;}
break;
============
处理成语句块,限制它的可见域,这样就好了,所以我
这样理解的
myfriend023 2006-12-12
  • 打赏
  • 举报
回复
up
等高人
CppPower 2006-12-12
  • 打赏
  • 举报
回复
第一、楼主请检查你的代码
第二、case也算是语句作用域

65,176

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧