`
weiyinchao88
  • 浏览: 1180885 次
文章分类
社区版块
存档分类
最新评论

【C/C++】error: jump to case label

 
阅读更多

problem

The following is not allowed:

switch (a)
{
case 1:
int a = 6;
//stuff
break;

case 2:
//stuff
break;
}


The following is allowed:

switch (a)
{
case 1:
{
int a = 6;
//stuff
}
break;

case 2:
//stuff
break;
}

来自实际项目的一段代码,简化形式如下:
switch (t)
{
case 0:
int a = 0;
break;
default:
break;
}
有什么问题吗?似乎没有。请用编译器编译一下……
嗯?!一个错误“error C2361: initialization of 'a' is skipped by 'default' label”。这怎么可能?
几番思琢,悟出解释:C++约定,在块语句中,对象的作用域从对象的声明语句开始直到块语句的结束,也就是说default标号后的语句是可以使用对象a的。如果程序执行时从switch处跳到default处,就会导致对象a没有被正确地初始化。确保对象的初始化可是C++的重要设计哲学,所以编译器会很严格地检查这种违例情况,像上述的示例代码中default语句后面并没有使用a,但考虑到以后代码的改动可能无意中使用,所以一样被封杀。
明白了原因,解决起来就很容易了。只要明确地限制对象a的作用域就行了。
switch (t)
{
case 0:
{ //added for fix problem
int a = 0;
break;
} //added for fix problem
default:
break;
}
如果确实需要在整个switch语句中使用对象a,那就把int a = 0;移到switch语句之前即可。不过从原先的语句看,其意图似乎并不是这样的,所以推荐前面的解决方案。


结束了吗?没有。让我们继续考究错误提示信息中“initialization”(也就是初始化)的确切含义。C++很看重初始化,所以往往会给我们造成一种错觉,似乎对象在定义处一定会经过初始化过程。真实情况如何呢?还是用实例来证明吧。
switch (t)
{
case 0:
int a;
a = 0;
break;
default:
break;
}
编译,这次没有报错。很明显int a;定义了对象,但没有进行初始化,否则就应该报告原先的错误。
再看看用户自定义类型。
class B
{
};

switch (t)
{
case 0:
B b;
break;
default:
break;
}
编译结果也没有错误,所以没有提供构造器的类仍然没有初始化过程。
如果给类加入构造器,情况就不同了。
class B
{
public: //added for initialization
B(){} //added for initialization
};
这样就能重现原先的错误。证明有了构造器,编译器就将进行初始化处理并对之进行安全检查。


从上面的实验,可以直观地体验到一些基本的C++观念和原理,并提高认识深度。
1.int a = 0;既是声明也是定义,还包括初始化;int a;是声明还是定义依上下文而定,但如果是定义就不会包括初始化;a = 0;仅仅是赋值语句,在此句前对象已经存在了。
2.为了避免不必要的开销,默认情况下,即程序员没有在代码中明确指示时,编译器不提供初始化过程。某些需要确保初始化的类,请提供构造器。这里透露出一个C++的设计哲学:通常你会面对多种选择,所以请精确地控制代码,其收益则是可以自由取舍调配的安全性、速度、内存开销等程序特性。
3.严密注意程序中标号的使用情况,特别是case、default等常规标号,否则他们可能会破坏对象的正确状态。如果提供了对象初始化,则能够获得编译器的额外帮助。

问题:
1>
"
如果程序执行时从switch处跳到default处,就会导致对象a没有被正确地初始化。确保对象的初始化可是C++的重要设计哲学,所以编译器会很严格地检查这种违例情况,像上述的示例代码中default语句后面并没有使用a,但考虑到以后代码的改动可能无意中使用,所以一样被封杀。
"
它还会考虑到以后代码的改动可能无意中使用这种情况吗?

2>
class B
{
};
为什么声明一个B对象时作者说没有初始化,类不是在没有声明构造函数时会用它的默认构造函数来初始化对象吗?为什么作者说没有初始化呢?

3>
为什么说没有初始化就会出问题呢?在C++中所有对象一定要初始化?不是这样的吧.
作者好像就这个意思啊.!

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

首先要承认作者提出这个问题很好,很多人都会碰上的这种情况,但是他本身对这个问题的理解个人认为存在误区或者说不到位。
下面是我的分析:
代码:
switch (t) { case 0: int a = 0; break; default: break; }
g++ 下的错误提示是:
case_init.cpp:9: error: jump to case label
case_init.cpp:7: error: crosses initialization of `int a'
首先在这里作者提到问题出在本地(local)变量或者叫做自动变量的作用域范围,点的很好。本地变量的作用域仅在花括号之间。于是方案1:
代码:
switch (t) { case 0: { //added for fix problem int a = 0; break; } //added for fix problem default: break; }
问题得到解决,在新的约束范围内,变量 a 很好的工作,而且也正确的实现了意图。接着方案2:
代码:
switch (t) { case 0: int a; a = 0; break; default: break; }
也没错。似乎两个方案都完成了目的,而且等价。于是作者把注意力完全转移到初始化问题上,纠住不放,到最后也没讲清楚为何有时候可以初始化,有时候确不能。
其实再深入一步,就完全清楚了,我把程序改动了一下,加了几个打印语句:
代码:
#include <stdio.h> int main() { printf("请输入一个数字: "); int t; scanf("%d", &t); switch (t) { case 0: int a; printf("/n a = %d/n", a = 0); break; case 1: printf("/n a = %d/n", a = 1); break; default: printf("/n a = %d/n", a = t); break; } }
编译通过,然后运行一下看看,一切正常。可能有人会很奇怪, int a 是在 case 0 中声明的呀!如果运行时选择 1,不就跳过去了吗?怎么在 case 1 和 default 中也能用呀?
殊不知不管你是有没有选 0, 这样定义的局部变量 a 在它的作用域(从声明处到结束花括号)范围之内
都有效。
到这里该明白编译器为何对 int a = 0; 初始化作出反应吧!
虽然你自己知道只在 case 0 中用到 a,在 case 1 或 default 中都不会用到 a(非上例),但编译器不懂你的心思,
为了避免在其它地方用到该变量出现不必要的麻烦,做一个出错提醒。 至于下面这个 class 的例子,道理一样。
所谓尽信书不如无书,何况并非大师的手笔,我们看的时候得多长个心眼,多动动手有助于问题分析。
<!-- / message --><!-- sig --><!-- / message -->
分享到:
评论

相关推荐

    mingwC/C++编译器

    wxgcc是一个开源的C/C++编辑软件,该软件轻型小巧,支持代码高亮,支持即时输入即时运行;是对著名的GCC开源编译工具的简单图形前端实现,通过wxpython语言开发而成。支持Windows XP,Windows 7 和 Linux 等多个平台...

    Dev-cpp5.4.0及API帮助文档 2018年蓝桥杯C语言/c++

    Dev-cpp5.4.0及API帮助文档 2018年蓝桥杯C语言/c++ 需要的同学可以下载使用

    C语言/C++集成开发环境 Dev-C++

    C语言/C++集成开发环境 Dev-C++。一款优秀的C/C++集成开发软件。

    C语言/C++ 烟花表白代码

    C语言/C++ 烟花表白代码 C语言/C++ 烟花表白代码 C语言/C++ 烟花表白代码 C语言/C++ 烟花表白代码

    C++17 标准 ISOIEC 14882 2017 官方pdf文档

    In addition to the facilities provided by C, C++ provides additional data types, classes, templates, exceptions, namespaces, operator overloading, function name overloading, references, free store ...

    C/C++ DevTools Support (DWARF)

    C/C++ DevTools Support (DWARF)离线安装包,里面是crx文件,如果不知道goole crx文件怎么安装的请自行搜索

    C/C++ and Matlab types convertor

    Each time you must convert mxArray to C/C++ types, do some job, and finally convert C/C++ types back to returned mxArray. This project provides easy access to above tasks given appropriate iterators...

    C语言/C++基础之爱心源码

    C语言/C++基础之爱心源码,适合初学C语言/C++的小伙伴学习研究,博客中有对应的讲解和演示,避免走弯路,费时费力。也真心希望能够帮助正在苦学C语言/C++ 程序设计的小伙伴们,你们的成长是我最大的幸福

    c/c++中文帮助文档(API)

    c/c++中文帮助文档(API),包含c和c++所有的库函数

    二维码(QRcode)生成算法 C语言/C++源码

    #二维码(QRcode)生成算法 C语言/C++ 源码 1. 根据输入字符串识别编码模式; 2. 根据输入字符串长度选择合适的QRcode版本; 3. 将编码转换为二进制位流表示为数据码字; 4. 使用多项式生成纠错码; 5. 将数据码和...

    c/c++:strlen源码

    c/c++:strlen源码

    C语言/C++基础之爱心程序源码

    C语言/C++基础之爱心程序源码,适合初学C语言/C++的小伙伴学习研究,博客中有对应的讲解和演示,避免走弯路,费时费力。也真心希望能够帮助正在苦学C语言/C++ 程序设计的小伙伴们,你们的成长是我最大的幸福

    c语言/c++/qt图形界面

    c语言/c++/qt图形界面

    C语言/C++基础之冰墩墩源码

    C语言/C++基础之冰墩墩源码,适合初学C语言/C++的小伙伴学习研究,博客中有对应的讲解和演示,避免走弯路,费时费力。也真心希望能够帮助正在苦学C语言/C++ 程序设计的小伙伴们,你们的成长是我最大的幸福

    基于C语言/C++基础的跨年烟花代码

    C语言/C++基础之跨年烟花代码,适合初学C语言/C++的小伙伴学习研究,博客中有对应的讲解和演示,避免走弯路,费时费力。也真心希望能够帮助正在苦学C语言/C++ 程序设计的小伙伴们,你们的成长是我最大的幸福

    C语言/C++基础之跨年烟花代码

    C语言/C++基础之跨年烟花代码,适合初学C语言/C++的小伙伴学习研究,博客中有对应的讲解和演示,避免走弯路,费时费力。也真心希望能够帮助正在苦学C语言/C++ 程序设计的小伙伴们,你们的成长是我最大的幸福

    MATLAB Support for MinGW-w64 C/C++ Compiler.rar

    资源是笔者在MATLAB里面安装的MinGW-w64 C/C++编译器安装包,主要用于作为博文https://blog.csdn.net/jiqiren_dasheng/article/details/103759720的资源附件。(声明:上传时积分设置的1,如果数值后续变了,就是...

    C/C++程序设计学习与实验系统 V2008.13.part1

    同时,为了便于C语言学习,加入C语言流程控制语句演示动画、C语言学习指导、可以方便地进行网络上和本机上的C/C++程序进行对照输入练习、入门程序实例、典型源程序、典型的函数算法,课程设计指导、课程设计源程序、...

    C/C++经典项目开发:C++打造远程桌面监控系统监控.txt

    本视频为C/C++编程经典项目之C++远程桌面监控系统。主要利用C语言知识以及C++编程知识以及少量算法、数据结构的知识来制作,本视频并不建议完全零基础的小伙伴下载学习,因为其中的语法知识或者代码名词可能会对于零...

Global site tag (gtag.js) - Google Analytics