错误:跳转到 switch 语句中的 case 标签
我编写了一个涉及使用 switch 语句的程序,但是在编译时它显示:
错误:跳转到案例标签。
为什么要这样做?
#include <iostream>
int main()
{
int choice;
std::cin >> choice;
switch(choice)
{
case 1:
int i=0;
break;
case 2: // error here
}
}
I wrote a program which involves use of switch statements, however on compilation it shows:
Error: Jump to case label.
Why does it do that?
#include <iostream>
int main()
{
int choice;
std::cin >> choice;
switch(choice)
{
case 1:
int i=0;
break;
case 2: // error here
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
问题是,除非使用显式的
{ }
块,否则在一个case
中声明的变量在后续case
中仍然可见,< em>但是它们不会被初始化,因为初始化代码属于另一个case
。在下面的代码中,如果 foo 等于 1,一切正常,但如果它等于 2,我们会意外地使用确实存在但可能包含垃圾的
i
变量。将 case 包装在显式块中可以解决问题:
编辑
为了进一步详细说明,
switch
语句只是一种特别奇特的goto
类型。下面是一段类似的代码,显示了相同的问题,但使用了goto
而不是switch
:The problem is that variables declared in one
case
are still visible in the subsequentcase
s unless an explicit{ }
block is used, but they will not be initialized because the initialization code belongs to anothercase
.In the following code, if
foo
equals 1, everything is ok, but if it equals 2, we'll accidentally use thei
variable which does exist but probably contains garbage.Wrapping the case in an explicit block solves the problem:
Edit
To further elaborate,
switch
statements are just a particularly fancy kind of agoto
. Here's an analoguous piece of code exhibiting the same issue but using agoto
instead of aswitch
:case 语句中声明新变量是导致问题的原因。将所有
case
语句包含在{}
中会将新声明的变量的范围限制为当前正在执行的 case,从而解决问题。Declaration of new variables in case statements is what causing problems. Enclosing all
case
statements in{}
will limit the scope of newly declared variables to the currently executing case which solves the problem.跳过某些初始化的 C++11 标准
JohannesD 给出了解释,现在为标准。
C++11 N3337 标准草案 6.7“声明声明”说:
从 GCC 5.2 开始,错误消息现在显示:
C
的初始化C允许这样做:c99转到过去的初始化
C99 N1256 标准草案 附件一“常见警告” ” 说:
C++11 standard on jumping over some initializations
JohannesD gave an explanation, now for the standards.
The C++11 N3337 standard draft 6.7 "Declaration statement" says:
As of GCC 5.2, the error message now says:
C
C allows it: c99 goto past initialization
The C99 N1256 standard draft Annex I "Common warnings" says:
JohannesD的答案是正确的,但我觉得问题的某个方面并不完全清楚。
他给出的示例在情况 1 中声明并初始化变量
i
,然后尝试在情况 2 中使用它。他的论点是,如果直接切换到情况 2,i
code> 将在未初始化的情况下使用,这就是出现编译错误的原因。此时,人们可能会认为,如果在一种情况下声明的变量在其他情况下从未使用过,那就没有问题。例如:人们可以期望这个程序能够编译,因为
i
和j
都只在声明它们的情况下使用。不幸的是,在 C++ 中它无法编译:正如 Ciro Santilli 包子露宪六四事件法轮功所解释的,我们根本就可以' t 跳转到case 2:
,因为这会跳过带有i
初始化的声明,即使case 2
不使用i
根本没有,这在 C++ 中仍然是被禁止的。有趣的是,通过一些调整(将
#ifdef
更改为#include
相应的标头,并在标签后添加分号,因为 标签后面只能跟语句,声明不算作 C 中的语句),该程序确实编译为 C:感谢在线编译器就像 http://rextester.com 您可以快速尝试使用 MSVC、GCC 或 Clang 将其编译为 C 或 C++ 。作为 C,它总是有效(只需记住设置 STDIN!),作为 C++,没有编译器接受它。
JohannesD's answer is correct, but I feel it isn't entirely clear on an aspect of the problem.
The example he gives declares and initializes the variable
i
in case 1, and then tries to use it in case 2. His argument is that if the switch went straight to case 2,i
would be used without being initialized, and this is why there's a compilation error. At this point, one could think that there would be no problem if variables declared in a case were never used in other cases. For example:One could expect this program to compile, since both
i
andj
are used only inside the cases that declare them. Unfortunately, in C++ it doesn't compile: as Ciro Santilli 包子露宪 六四事件 法轮功 explained, we simply can't jump tocase 2:
, because this would skip the declaration with initialization ofi
, and even thoughcase 2
doesn't usei
at all, this is still forbidden in C++.Interestingly, with some adjustments (an
#ifdef
to#include
the appropriate header, and a semicolon after the labels, because labels can only be followed by statements, and declarations do not count as statements in C), this program does compile as C:Thanks to an online compiler like http://rextester.com you can quickly try to compile it either as C or C++, using MSVC, GCC or Clang. As C it always works (just remember to set STDIN!), as C++ no compiler accepts it.