switch里面的case,似乎不是一种if判断,而是很复杂的东东

zserewr 2015-12-31 09:41:11
例如:
case不合条件的时候,似乎就是一个if。
而一旦符合条件的case找到了,除非有break,否则一直执行,其他的case没有if的作用:

int main()
{
int n=3;
switch(n)
{
default:cout<<"default"<<endl;
case 2:cout<<"2"<<endl;
case 3:cout<<"3"<<endl;
case 4:cout<<"4"<<endl;
case 5:cout<<"5"<<endl;
}
return 0;
}

输出是

3,4,5

而如果n的初始值是6,那么将打印:

default
2
3
4
5

问题:
(1) default语句写在哪里,书上说不重要,因为default最后匹配。但是在我的例子里面n=6的时候,default语句确实先执行了。

如果程序先判断default下面的4个case都不符合,然后执行default,说明default还是最后执行的。那为什么之后再次进入了4个case对应的语句呢?

(2) 为什么case一旦符合,那么除非有break,否则其他的case似乎起不到if的作用。
换句话说,switch/case并不等同于if/else if/else这样的逻辑判断。

我知道if语句最后会生成类似jnz这样的跳转指令,那么switch/case这样奇怪的语义,会生成什么指令呢? 因为case不合条件的时候似乎是jnz,而符合条件就被忽略了,直到遇到break。

(3)switch/case这样的语义被编译成什么样的intel汇编指令?
...全文
695 14 打赏 收藏 转发到动态 举报
写回复
用AI写文章
14 条回复
切换为时间正序
请发表友善的回复…
发表回复
Anéeka 2019-03-30
  • 打赏
  • 举报
回复
其实switch case很低级的,case只能接int和char常量。select case比它强大得多,可以接各种类型的常量变量甚至表达式。就不知道select case和switch case哪个效率更高,求大佬科普
qq_33587745 2016-01-01
  • 打赏
  • 举报
回复
从上到下寻找对应的值 不匹配就找default 但是由于没有break停止 就又从上到下输出一次呀
lm_whales 2015-12-31
  • 打赏
  • 举报
回复
switch 用在循环中,switch 内的 break 不能跳出循环, 和if 相比,这是不便之处
lm_whales 2015-12-31
  • 打赏
  • 举报
回复
switch 在状况比较多, 要执行的代码比较复杂, 尤其是标号连续的时候, 要比if else 高效, 相比之下,很多的if else 嵌套,效率就低了。 n+1 分支的 if(e1)s1; else if(e2)s2; else s3; 的话 如果需要执行到最后两个分支, 需要比较n次。 switch 只对 情况作一次判断 ,含有 defualt 的最多两次,就可以跳入不同分支 从代码上看 switch 语句,代码也比 if(e1)s1; else if(e2)s2; else s3; 可读性好。 结构清晰。 多分支 尽可能,用switch 分支少 if(e1)s1; else if(e2)s2; else s3; 更好。
赵4老师 2015-12-31
  • 打赏
  • 举报
回复
理解讨论之前请先学会如何观察! 计算机组成原理→DOS命令→汇编语言→C语言(不包括C++)、代码书写规范→数据结构、编译原理、操作系统→计算机网络、数据库原理、正则表达式→其它语言(包括C++)、架构…… 对学习编程者的忠告: 多用小脑和手,少用大脑、眼睛和嘴,会更快地学会编程! 眼过千遍不如手过一遍! 书看千行不如手敲一行! 手敲千行不如单步一行! 单步源代码千行不如单步Debug版对应汇编一行! 单步Debug版对应汇编千行不如单步Release版对应汇编一行! 不会单步Release版对应汇编?在你想单步Release版C/C++代码片断的前面临时加一句DebugBreak();重建所有,然后在IDE中运行。(一般人我不告诉他!单步类的实例“构造”或“复制”或“作为函数参数”或“作为函数返回值返回”或“参加各种运算”或“退出作用域”的语句对应的汇编代码几步后,就会来到该类的“构造函数”或“复制构造函数”或“运算符重载”或“析构函数”对应的C/C++源代码处。 VC调试时按Alt+8、Alt+7、Alt+6和Alt+5,打开汇编窗口、堆栈窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应堆栈、内存和寄存器变化,这样过一遍不就啥都明白了吗。 对VC来说,所谓‘调试时’就是编译连接通过以后,按F10或F11键单步执行一步以后的时候,或者在某行按F9设了断点后按F5执行停在该断点处的时候。
lm_whales 2015-12-31
  • 打赏
  • 举报
回复
switch 是跳去执行标号对应的程序段。 case 是标号: break 是跳出这个程序段 default 大概是个 else 差不多的东西。 具体实现,当然要复杂些,因为 case 对应的常量情况比较复杂, 又连续的,有不连续的,而且也不必顺序写。 switch 一般用跳转表实现。 也可能是地址表 简单的,可以直接查表
Saleayas 2015-12-31
  • 打赏
  • 举报
回复
default 不是最后匹配,而是缺省匹配。 而且 switch 和 if-else 不同。 switch 使用的一种类似查表得方式,根据参数直接找到 case 的入口。 如果和任何入口都不匹配,那么将使用 default 入口,不是一个一个去比较的。 至于他们的位置是无关的, case 和 default 仅仅是标号的,可以作为 goto 的参数的。 break 也仅仅是一个语法,甚至于你可以在 switch 和 循环混合使用 break 语法。(莫名其妙无穷)
lilianjie001 2015-12-31
  • 打赏
  • 举报
回复
case语句根据自己的程序逻辑来确定后面是否加break。 无论default 位置在前还是在后,都是先判断 各个case, 最后才进 default。 无论 进入某个 case 或 default,程序要 执行到 break,或开关的结束 才终止。 default:cout<<"default"<<endl; case 2:cout<<"2"<<endl; case 3:cout<<"3"<<endl; case 4:cout<<"4"<<endl; case 5:cout<<"5"<<endl; 你这段代码里面没有break语句,所以default后面的语句会继续执行的。
zserewr 2015-12-31
  • 打赏
  • 举报
回复
引用 1 楼 wxq714586001 的回复:
首先,每个case下要根据情况加上break; (1)这是因为当n=6时不匹配2,3,4,5,所以从default开始执行。由于代码没有break,会依次执行之后的case语句; (2)switch...case...我好像记得编译器是将每个条件判断转换为一个偏移量; (3)可以用gcc或vs看一下汇编;
那么,在下面n=6的情况下:

int main()
{
    int n=6;
    switch(n)
    {
        default:cout<<"default"<<endl;
        case 2:cout<<"2"<<endl;
        case 3:cout<<"3"<<endl;
        case 4:cout<<"4"<<endl;
        case 5:cout<<"5"<<endl;
    }
    return 0;
}
岂不是: 进入switch以后,先case2,不符合,再case3,不合符,再case4,不合符,再case5,不符合,然后default 之后因为没有break,所以case2跳过判断直接执行,case3跳过判断直接执行,case4跳过判断直接执行,case5跳过判断直接执行。 换句话说,case 2其实被执行了两遍,第一遍是刚进入switch的时候,判断是否符合条件,第二遍是default执行完以后,不判断case的条件而直接执行cout<<"2"。 是这样的吗?
牧羊人Full 2015-12-31
  • 打赏
  • 举报
回复
首先,每个case下要根据情况加上break; (1)这是因为当n=6时不匹配2,3,4,5,所以从default开始执行。由于代码没有break,会依次执行之后的case语句; (2)switch...case...我好像记得编译器是将每个条件判断转换为一个偏移量; (3)可以用gcc或vs看一下汇编;
zserewr 2015-12-31
  • 打赏
  • 举报
回复
引用 7 楼 lm_whales 的回复:
switch 在状况比较多, 要执行的代码比较复杂, 尤其是标号连续的时候, 要比if else 高效, 相比之下,很多的if else 嵌套,效率就低了。 n+1 分支的 if(e1)s1; else if(e2)s2; else s3; 的话 如果需要执行到最后两个分支, 需要比较n次。 switch 只对 情况作一次判断 ,含有 defualt 的最多两次,就可以跳入不同分支 从代码上看 switch 语句,代码也比 if(e1)s1; else if(e2)s2; else s3; 可读性好。 结构清晰。 多分支 尽可能,用switch 分支少 if(e1)s1; else if(e2)s2; else s3; 更好。
也就是查表法! 多谢了!
paschen 2015-12-31
  • 打赏
  • 举报
回复
switch 中 你case defualt 怎么排都不影响,编译器不是一条一条去比较,所以在多分支下效率会比if 高 switch中各选项会被重新排列到一个地址表(有序的)里,然后计算出跳转位置 case后没有break会一直往下掉 想具体了解可以看:《C++反汇编与逆向分析技术揭秘》
zhouxiaofeng1021 2015-12-31
  • 打赏
  • 举报
回复
引用 1 楼 wxq714586001 的回复:
首先,每个case下要根据情况加上break; (1)这是因为当n=6时不匹配2,3,4,5,所以从default开始执行。由于代码没有break,会依次执行之后的case语句; (2)switch...case...我好像记得编译器是将每个条件判断转换为一个偏移量; (3)可以用gcc或vs看一下汇编;
说得对
haierpro 2015-12-31
  • 打赏
  • 举报
回复
可能是如下结构, 但不一定是,要看case 值的分布与编译器的支持, 希望能帮到你: //switch(n) Array[] = {0,label1,label2,label3}; if (n > 0 && n < sizeof(Array)-1) { goto Array[n]; } else { goto label_default; } //{ label_default: cout<<"default"<<endl; label1: //case 1: cout<<1<<endl; goto label_end; //break; label2: //case 2: cout<<2<<endl; label3: //case 3: cout<<3<<endl; label_end: //}

69,371

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧