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,当然编译通过,连警告都没有。

总结起来就是:

  1. C 编译器允许一个 case 使用另一个 case 后声明定义的变量,但是 C++ 语法不允许这个
  2. 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 内定义变量的问题的更多相关文章

  1. case中定义变量

    1.c语言switch/case中定义变量   case 0: int b = 0 ; printf("0");break; case 1: printf("1" ...

  2. c/c++ switch case内括号

    如果在case语句中有定义变量,则必须要加{},否则会报错.

  3. java中的Switch case语句

    java中的Switch case 语句 在Switch语句中有4个关键字:switch,case break,default. 在switch(变量),变量只能是整型或者字符型,程序先读出这个变量的 ...

  4. ansible中定义变量的若干方法

    Ansible支持十几种定义变量的方式 根据优先级排序的定义方式: Inventory变量 Host Facts变量 Playbook变量 Playbook提示变量 变量文件 命令行变量 1.Inve ...

  5. switch语句下的变量声明和定义

    switch语句下的变量声明和定义的问题: switch...case...语句中存在声明和定义会出现一些问题.这个由switch语法特性决定的, switch中每个case都是平等的层次,区别于一般 ...

  6. swtich和case语句中,定义变量要加花括号

    转自: http://blog.chinaunix.net/uid-27103408-id-3340702.html http://www.xuebuyuan.com/2070170.html swi ...

  7. C++在循环内和循环外定义变量的差异

    原文:http://blog.csdn.net/cashey1991/article/details/45127561 最后总结: 对于使用int等基本数据类型作为循环变量,只要你用的优化方面足够给力 ...

  8. Thymeleaf 之 内置对象、定义变量、URL参数及标签自定义属性

    Thymeleaf 之 内置对象.定义变量.URL参数及标签自定义属性 本文章来自[知识林] 如标题所述,这篇文章主要讲述Thymeleaf中的内置对象(list解析.日期格式化.数字格式化等).定义 ...

  9. 在函数内部定义的变量加与不加var的区别,匿名函数和有名函数内声明变量的区别

    2014年4月21日,14:49分: 原创:http://www.cnblogs.com/liujinyu/p/3678523.html 今天写天气网英文版的产品频道,maps页面的js时,偶然意识到 ...

随机推荐

  1. 2018年手机应用UI设计趋势预测

    用户需求瞬息万变,而手机软件UI设计为适应变化的用户需求,也相应的发生着变化.但是,这并不意味着用户需求和UI设计趋势就是无迹可寻的.事实上,根据前几年的手机app界面设计变化的特点,尤其是2017年 ...

  2. 【转载】小结一下linux 2.6内核的四种IO调度算法

    在LINUX 2.6中,有四种关于IO的调度算法,下面综合小结一下: 1) NOOP NOOP算法的全写为No Operation.该算法实现了最最简单的FIFO队列,所有IO请求大致按照先来后到的顺 ...

  3. 简单的vuex 的使用

    1. npm install vuex 2. 在src 下 新建文件夹 store (为什么是这个单词,vuex 是用来状态管理的,用储存一些组件的状态,取存贮之意),store 文件下 新建文件 i ...

  4. gitignore文件的作用

    早上上传文件的时候,发现有一些密钥不需要增加到版本库中,但是由于每次git status都会提示Untracked files ...并且这些文件并不需要一直提示,会占用相应的需要跟踪的文件位置,导致 ...

  5. 记录一下自己爬虎牙LOL主播的爬虫思路

    1.明确爬虫目的 爬虫目的需要我们明确的,没有目的的爬虫都是耍流氓!像我这次爬虫目的能不能从网页上爬下来. 2.怎么来爬? a. 先要找到具有唯一性的标签 <li class="gam ...

  6. SpringBoot入坑-持久化操作

    前面内容中我们已经了解到了SpringBoot关于参数传递的相关知识,本篇我们一起来学习一下SpringBoot关于数据库持久化操作的知识,这里我们使用JPA进行数据库的持久化操作. 首先由于我们需要 ...

  7. cobaltstrike安装加破解教程+使用教程

    1.先安装java环境= = 1. 下载1.8u121的JAVA JDK (新的java JDK不稳定)!!原因:https://blog.cobaltstrike.com/2017/04/26/ja ...

  8. struts2(三)之表单参数自动封装与参数类型自动转换

    前言 对struts2的使用不外乎这几点,参数自动封装,拦截器的使用,数据校验,ognl表达(值栈和actionContext的讲解),struts2的标签,struts2的国际化, struts2的 ...

  9. DFS中的奇偶剪枝学习笔记

    奇偶剪枝学习笔记 描述 编辑 现假设起点为(sx,sy),终点为(ex,ey),给定t步恰好走到终点, s | | | + — — — e 如图所示(“|”竖走,“—”横走,“+”转弯),易证abs( ...

  10. 2017ecjtu-summer training # 9 HDU 4544

    湫湫系列故事--消灭兔子 Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)Tota ...