日期:2014-05-18  浏览次数:21160 次

switch 里面的case 分支是从上往下一个个判断的么
我看了一下中间语言,他是把所有的case的变量集中起来,然后判断是否跟某个变量相等,如果相等,就转到相应的处理
但是这个判断也是从上往下比较是不是和这些变量相等的把,那和if else按顺序判断不是一样的么。



vs里面case加不了断点,f11就直接进入到分支了,但是实际上,是不是从上往下case都判断过呢




------解决方案--------------------
我也感觉是这样的,因为中间语言看了好像是这样,只不过是switch形成了一个中间表的样子,但是用那个变量值和表中的值比较的时候 好像也是从上往下比较的吧


=========================================

你要明白什么是hash表,什么是内存寻址 就不会这么认为了。 基址+偏移量。也就是说就算他是生成了一个中间表他一不会去全体扫描,他只会直接算出偏移量,然后直接跳转过去就ok
------解决方案--------------------
探讨
1.1楼的回复是告诉你,有些事情其实没必要追究,我们根本关心“回”字到滴有多少种写法,那是“站着穿长衫的人”才会研究的。
2.swich做为一个基本流程控制语法,甚至在世界上第一个女程序员时代就已经被建立,如果这玩意到现在还有啥问题,那么这100年程序员们都在干啥呢?

3.你做个简单实验,你在swich里面做两个的分支。

swich(a)
case 1:
break;……

------解决方案--------------------
探讨


嘿嘿,好像说道点子上了,“他只会直接算出偏移量?” 这个偏移量他咋计算的呢。或者说我这问题问的太菜鸟了,能不能 给个相关的关键词,我百度搜索相关的文章,好好普及一下,再来请教?谢谢!


------解决方案--------------------
逻辑上是从上向下顺序查找的,楼主钻研的精神可嘉
------解决方案--------------------
探讨
引用:
引用:


嘿嘿,好像说道点子上了,“他只会直接算出偏移量?” 这个偏移量他咋计算的呢。或者说我这问题问的太菜鸟了,能不能 给个相关的关键词,我百度搜索相关的文章,好好普及一下,再来请教?谢谢!



这个不是很好用文字表达,hash表的存储方式并不是使用连续内存存储,他是使用基地址+偏移量存储

比 1,3,5 相当于下面的表述
……

------解决方案--------------------
还是深了,不赞同lz这样做,但是精神无疑是好的。
如果是我的话,我肯定是先解决吃饭问题,然后在解决吃什么的问题,最后在讨论为什么吃这些东西的问题。
------解决方案--------------------
可以看看stackoverflow上关于这个讨论
http://stackoverflow.com/questions/3366376/are-net-switch-statements-hashed-or-indexed

我说一下我的理解。首先不像C/C++一样,C#的switch除了支持数字,还支持字符串类型。
字符串比较简单,先说字符串,如果case个数较少的话,C#会用if else这样的方式来实现,就像41楼列出来的一样,从前往后一个个比较;如果个数较多的话(我也不知道具体多少算多),C#会new一个Dictionary来实现快速查找,Dictionary基本上就是一个hashtable,把字符串映射到一些连续的数字上(注意,是连续的,这很重要,并不是简单的GetHashCode返回的乱七八糟的数字),然后再switch这个数字。

再说数字的,数字的也要分情况,如果那些case里的数字是离散的,那C#也是会用if else来实现;如果是一串连续的数字,像1,2,3,这时候就会用il里定义的switch指令 ,像这样 switch( IL_0229, IL_0239, IL_0249),这三个行号放在一块叫跳转表(jump table), 这个switch指令的执行我猜是这样的(我没看过il的教程,纯粹是猜测),判断当前寄存器里的值,如果值为0,那么跳转到IL_0229这行,如果值为1,则跳转到IL_0239,2则跳IL_0249。这个动作是O(1)的,不需要一个一个判断。注意这里寄存器里的值是连续的,只能从0往上加,如果你case的第一个不是0,编译器会先做一些四则运算把它变成0,就像1,2,3的话减去1就可以了。 如果你给的case里又有连续又有离散的呢,比方说我有4个值,1,2,3,100,这时候我发现编译器会先if else一下是不是100,如果不是的话剩下那1,2,3又可以switch了,反正这个是考验编译器智商的了,尽可能的优化。

如果你还想问il里的switch到底是怎么实现o(1)的跳转的,可以看一下编译成x86后的代码,类似于这行,
jmp dword ptr [eax*4+002B2878h] 

至于vs里f11单步不到中间的判断过程(即使是开启显示汇编),我觉得是vs考虑到大多数人没有想要看那些中间过程,而是想直接知道跳到哪个case了,所以把这个过程有意隐藏了
------解决方案--------------------
建议到80X86 微机原理上看看,我以前看到过,好像是跳转的,不是逐条的
------解决方案--------------------
mark晚上回去想想。 “47”楼应该接近答案了。