Switch-case 内定义变量的问题
Switch-case 内定义变量的问题
这个问题需要分开讨论,C 语言和 C++ 的标准定义是不同的。
C++
int Caset(int a) {
switch (a) {
case 1:
int b = 1;
std::cout<<"a==1: "<<b<<std::endl;
break;
case 2:
b = 2;
std::cout<<"a==2: "<<b<<std::endl;
break;
}
}
编译报错信息为
simple.cc:35:9: error: cannot jump from switch statement to this case label
case 2:
^
simple.cc:32:17: note: jump bypasses variable initialization
int b = 1;
^
也就是说,跳到 case2 的这个地方,忽略了对于 b 这个变量的初始化,这个很直观,就是在这里我找不到 b。
那么如果改成
int Caset(int a) {
switch (a) {
case 1:
int b;
b = 1;
std::cout<<"a==1: "<<b<<std::endl;
break;
case 2:
b = 2;
std::cout<<"a==2: "<<b<<std::endl;
break;
}
}
顺利成功,没有报错,如果 a 为 2,那么输出 b 也是 2,说明逻辑没有问题。那么问题来了,b 在前面声明,为什么后面可以用到呢,因为 switch-case 的逻辑控制就是用 label 来标记跳转的,而不是别的复杂的逻辑控制,所以 b 的作用域是在整个 switch 的花括号内,关于这个问题见知乎讨论请教switch内部的变量定义问题。
C 语言
上面两种写法统统出错,
void Caset(int a) {
switch (a) {
case 1:
/* one style */
int b;
b = 1;
/* another style */
int b = 1;
printf("1: %d", b);
break;
case 2:
b = 2;
printf("2: %d", b);
break;
}
}
两种写法都错
First style:
main.c:12:13: error: expected expression
int b;
^
main.c:13:13: error: use of undeclared identifier 'b'
b = 1;
^
Another style:
ttt.c:11:13: error: expected expression
int b = 1;
^
意思是说,此处需要一个表达式(expression),而不是一个变量声明初始化。有一个很黑客的做法,如下:
void Caset(int a) {
switch (a) {
case 1:
;
int b = 1;
// b = 1;
printf("1: %d \n", b);
break;
case 2:
b = 2;
printf("2: %d \n", b);
break;
}
}
这个很不能理解了,其实也就是说保证 case 后面跟着的确实是 expression 即可。考虑一下 C++ 代码出现的问题:跳过变量的声明?C 语言中同样跳过,但是编译器不认为这个是错误,而且逻辑上面也是没有问题的,在后面的 case 中可以正常给变量赋值,但是如果 case2 中,我不是给 b 赋值,而是直接访问 b,那返回的数值就是一个随机的错误的数据了,我在我的电脑上使用 gcc 编译,若直接读取数据,得到的是 0,当然编译通过,连警告都没有。
总结起来就是:
- C 编译器允许一个 case 使用另一个 case 后声明定义的变量,但是 C++ 语法不允许这个
- C 不允许 case 后面紧跟声明或定义,只允许表达式(expression); C++ 对这个没有限制
通用解法
当然我认为这样的代码可读性差,比较好的做法可以是将声明变量的事情放在头上做。
void Caset(int a) {
switch (a) {
int b;
case 1:
b = 1;
// b = 1;
printf("1: %d \n", b);
break;
case 2:
b = 2;
printf("2: %d \n", b);
break;
}
}
但是要留心, switch 和 case 之前那块地方也就只能写写这样的声明,写别的表达式,赋值啊什么的,统统是不会生效的。
参考:
Why can't variables be declared in a switch statement?这个链接中我个人比较推荐 AnT 的回答,讲清楚了问题的原因和解决方案的原理
Switch-case 内定义变量的问题的更多相关文章
- case中定义变量
1.c语言switch/case中定义变量 case 0: int b = 0 ; printf("0");break; case 1: printf("1" ...
- c/c++ switch case内括号
如果在case语句中有定义变量,则必须要加{},否则会报错.
- java中的Switch case语句
java中的Switch case 语句 在Switch语句中有4个关键字:switch,case break,default. 在switch(变量),变量只能是整型或者字符型,程序先读出这个变量的 ...
- ansible中定义变量的若干方法
Ansible支持十几种定义变量的方式 根据优先级排序的定义方式: Inventory变量 Host Facts变量 Playbook变量 Playbook提示变量 变量文件 命令行变量 1.Inve ...
- switch语句下的变量声明和定义
switch语句下的变量声明和定义的问题: switch...case...语句中存在声明和定义会出现一些问题.这个由switch语法特性决定的, switch中每个case都是平等的层次,区别于一般 ...
- swtich和case语句中,定义变量要加花括号
转自: http://blog.chinaunix.net/uid-27103408-id-3340702.html http://www.xuebuyuan.com/2070170.html swi ...
- C++在循环内和循环外定义变量的差异
原文:http://blog.csdn.net/cashey1991/article/details/45127561 最后总结: 对于使用int等基本数据类型作为循环变量,只要你用的优化方面足够给力 ...
- Thymeleaf 之 内置对象、定义变量、URL参数及标签自定义属性
Thymeleaf 之 内置对象.定义变量.URL参数及标签自定义属性 本文章来自[知识林] 如标题所述,这篇文章主要讲述Thymeleaf中的内置对象(list解析.日期格式化.数字格式化等).定义 ...
- 在函数内部定义的变量加与不加var的区别,匿名函数和有名函数内声明变量的区别
2014年4月21日,14:49分: 原创:http://www.cnblogs.com/liujinyu/p/3678523.html 今天写天气网英文版的产品频道,maps页面的js时,偶然意识到 ...
随机推荐
- [异常解决] 奇巧淫技——VirtualBox中的linux无显示启动,并在win7上远程控制
楼主是资深技术宅(癖),由于感觉手上的老笔记本太卡,遂狠心买了个性能至强的主机同时配了个投影仪(满足躺着打代码的意淫场景).但是体验了大概一个月发现还是坐着打代码舒服,但是如下图坐着打代码总是要抬头看 ...
- OS.path部分函数的介绍
OS.path模块中的部分函数的介绍 os.path.abspath(path) #返回绝对路径 os.path.basename(path) #返回文件名 os.path.commonprefix( ...
- 编写OC高质量的代码的有效方法
1. 写这个只是为了自己记忆,有相关pdf文件,如需要留下邮箱.. 2. 在类的头文件中尽量少引入其他头文件 除非确有必要,否则不要引入头文件.一般来说,应在某个类的头文件中使用向前声明来提及别的类( ...
- hibernate使用setResultTransformer()将SQL查询结果放入集合中
在平时开发中Hibernate提供的hql基本能够满足我们的日常需求.但是在有些特殊的情况下,还是需要使用原生的sql,并且希望sql查询出来的结果能够绑定到pojo上.hibernate API中的 ...
- Java实现 中文转换成Unicode编码 和 Unicode编码转换成中文
想要实现中文字符转换为Unicode编码的话主要用到的是一个这样的包,自己可以去API文档里面查看下的 java.util.Properties; 直接进入主题吧,主要是 package Test01 ...
- 初窥Flask
初窥Flask Flask是一个基于Python开发并且依赖jinja2模板和Werkzeug WSGI服务的一个微型框架,对于Werkzeug本质是Socket服务端,其用于接收http请求并对请求 ...
- 算法实现之python篇
Python source code: gradient_boosting_regression.py from sklearn import ensemblefrom sklearn.metrics ...
- 【Java学习笔记之十九】super在Java继承中的用法小结
1)有人写了个很好的初始化属性的构造函数,而你仅仅想要在其中添加另一些自己新建属性的初始化,这样在一个构造函数中调用另外一个构造函数,可以避免重复的代码量,减少工作量: 2)在一个构造函数中调用另外一 ...
- JS数组中shift()和push(),unshift()和pop()操作方法使用
Javascript为数组专门提供了push和pop()方法,以便实现类似栈的行为.来看下面的例子: var colors=new Array(); //创建一个数组 var count= ...
- Qt 共享库(动态链接库)和静态链接库的创建及调用
前言: 编译器 Qt Creator, 系统环境 win7 64 位 1.创建共享库: 新建文件或项目->选择 Library 和 c++ 库->选择共享库->下一步(工程名为 sh ...