浅析C/C++中的switch/case陷阱

浅析C/C++中的switch/case陷阱

  先看下面一段代码:

  文件main.cpp


#include<iostream>
using namespace std;

int main(int argc, char *argv[])
{
int a =0;
switch(a)
{
case 0: int b=1;cout<<b<<endl;break;
case 1: cout<<b<<endl;break;
default:break;
}
return 0;
}

  在gcc编译器下编译的结果为:

  提示跳过了变量b的初始化过程。对于一个局部变量,它的作用域为它所定义的地方到它所在的语句块结束为止,那么对于变量b,它所在的最小语句块为switch{}块,那么也就说在case
0后面的部分,变量b都是可见的(注意在case 0之前变量b是无法访问的)。考虑这样一种情况,当a的值为0,那么程序就跳到case
1执行,此时b虽然可以访问,但是跳过了它的初始化过程。而如果在定义变量的同时进行了初始化,表明程序员希望初始化这个变量,但是此时跳过了该变量的初始化,就可能导致程序出现程序员无法意料的情况,因此编译器为了避免跳过这样的初始化而造成无法预料的结果,就对该语句进行报错。

  如果将上述代码改为:

 switch(a)
{
case 0: int b;b=0;cout<<b<<endl;break;
case 1: cout<<b<<endl;break;
default: break;
}

  编译的结果为:

  只是进行了警告,因为在定义变量的时候没有进行初始化,也就是说程序怎么执行都不会跳过变量的初始化过程,不会说由于跳过了该过程而造成无法预料的错误或程序崩溃现象。因此只是进行了警告。

  再看下面这段代码:

 switch(a)
{
case 0: break;
default: int b=1;cout<<b<<endl;break;
}

  这段代码没有报错。因为如果执行case 0,变量b没有进行初始化,但是由于在case
0部分b是不可见的,因此不会对程序造成任何影响,而如果执行default分支,则b会被初始化,因此程序没有报错。

  归根到底,出现上述的crosses initialization和jump to case
label错误的原因是由于变量的作用域问题,因此一个好的习惯就是在case子句下面加上大括号来限定变量的作用域。

 switch(a)
{
case 0: {int b=1;cout<<b<<endl;break;}
case 1: break;
default: break;
}

  不过要注意,一旦加上了大括号,在case 0后面便不能访问到变量b了。

  注意,如果上述代码以C方式进行编译,编译结果则会有所不同:

  main.c


#include <stdio.h>
#include<stdlib.h>
int main(int argc, char *argv[])
{
int a =2;
switch(a)
{

case 0: int b=17;printf("%d\n",b);break;
case 1: break;
default:printf("%d\n",b);break;
}
return 0;
}

  编译结果:

  报的错误意思是在该标签下不能定义变量。为什么呢?原因很简单,在C语言中所有的变量定义都必须放到所在语句块的最前面。所以如果改成这样:


#include <stdio.h>
#include<stdlib.h>
int main(int argc, char *argv[])
{
int a =2;
switch(a)
{
int b=17;
case 0: printf("%d\n",b);break;
case 1: break;
default:printf("%d\n",b);break;
}
return 0;
}

  编译结果:

  没有报错,注意这里没有报crosses initialization的错误,这点C和C++有点不同。如果以C++方式编译,肯定会报crosses
initialization的错误,这也更加说明C++在语法方面要求比C更加严格。

  该程序运行的结果:

  输出32,是一个随机值。因为b并没有进行初始化,所以输出的是随机值。

  以上只是个人观点,若有不正之处,恳请指正,以免误导他人。

时间: 2024-08-27 16:58:26

浅析C/C++中的switch/case陷阱的相关文章

java中的Switch case语句

java中的Switch case 语句 在Switch语句中有4个关键字:switch,case break,default. 在switch(变量),变量只能是整型或者字符型,程序先读出这个变量的值,然后在各个"case"里查找哪个值和这个变量相等,如果相等,则条件成立,程序执行相应的分支,直到碰上break或有switch语句结束. 有几个需要着重注意的地方. 第一,前面说了switch(变量),只能是整型和字符类型. 第二,case之后是直接的常量数值. 第三,break使得程

react jsx 中使用 switch case 示例

<div> <span>适用平台:</span> <span>{(() => { switch (currentItems.usePlatform) { case 0: return '全平台可用' case 1: return '淘宝' case 2: return '美团' case 3: return '爱奇艺' case 4: return '腾讯' default: return null } } )()}</span></

C Language study - switch case and continue

本文讨论研究在switch case语句中如何使用continue关键字. 一般的switch case语句格式: switch(?) { case num1: //something break; case num2: //something break; case numx: //something break; default: //default break; } 或者: switch(?) { case char1: //something break; case char2: //s

C语言switch/case圈复杂度优化重构

软件重构是改善代码可读性.可扩展性.可维护性等目的的常见技术手段.圈复杂度作为一项软件质量度量指标,能从一定程度上反映这些内部质量需求(当然并不是全部),所以圈复杂度往往被很多项目采用作为软件质量的度量指标之一. C语言开发的项目中,switch/case代码块是一个很容易造成圈复杂度超标的语言特性,所以本文主要介绍下降低switch代码段的重构手段(如下图).switch圈复杂度优化重构可分为两部分:程序块的重构和case的重构.程序块重构是对代码的局部优化,而case重构是对代码的整体设计,

switch case 支持的 6 种数据类型!

有粉丝建议可以偶尔推送一些 Java 方面的基础知识,一方面可以帮助一初学者,也可以兼顾中高级的开发者. 那么今天就讲一下 Java 中的 switch case 语句吧,有忘记的同学正好可以温习一下. Java 中 switch case 语句用来判断一个变量与一系列值中某个值是否相等,每个值称为一个分支. 语法格式如下: switch(expression){ case value : //语句 break; //可选 case value : //语句 break; //可选 //你可以有

if、else if 、else及switch...case使用小记(C#)

有时候编程编的久了,如果不停下来认真思考一下,即便是一些最基础的知识点,也可能让自己懵圈.其实,说到底还是打基础的时候没打牢,或者说自以为是地认为自己懂了,然后在打基础的时候就懒得思考懒得看了,结果就是对这个基础知识点的认识一直停留在自己的固有认识里. 好了,下面进入正题.if.else if和else是我们经常要用到的基本语法结构.某日,在园子里看到一博客贴出了这样一个问题. 控制台输入一个成绩,如果 成绩>=90 :输出A,如果90>成绩>=80 输出B,如果80>成绩>

python技巧 switch case语句

不同于C语言和SHELL,python中没有switch case语句,关于为什么没有,官方的解释是这样的 使用Python模拟实现的方法: def switch_if(fun, x, y):    if fun == 'add':        return x + y    elif fun == 'sub':        return x - y    elif fun == 'mul':        return x * y    elif fun == 'div':       

switch...case的陷阱

switch...case的基本用法: switch(表达式) { case 常量表达式1: 语句1;(可包含多个语句,可不加大括号) break; case 常量表达式2: 语句2;(可包含多个语句,可不加大括号) ... default: 语句;(可包含多个语句,可不加大括号) } 书上会这么说: 注意case后面的常量表达式是冒号. 注意default是所有case都不成立时候的默认执行语句. 注意case往往要跟上break. 好了,就是这个break,C#的同学请坐下,我知道C#的ca

Switch Case语句中多个值匹配同一个代码块的写法

switch ($p) { case 'home': case '': $current_home = 'current'; break; case 'users.online': case 'users.location': case 'users.featured': case 'users.new': case 'users.browse': case 'users.search': case 'users.staff': $current_users = 'current'; break