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

解决方案 »

  1.   

    根本没有往下判断啊,只是判断switch变量是什么,然后根据这个变量跳到相应的case
      

  2.   

    楼上有道理,应该是先算出switch的值再跳到相应的分支,执行完就break
      

  3.   


    再跳转之前,有没有判断其他的case,这是我要问的关键
      

  4.   

    根据变量值查找哪个case,如果找不到就default,而if是从上往下层层进行判断
      

  5.   

    vs F8逐语句   shitf+F8  逐过程菜单栏》调试里 应该都有试试 逐语句
      

  6.   


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

  7.   


    vs 里面 f11就是逐语句,试过,case打不了断点
      

  8.   

    下断点调试就知道了,要跳出就得加break.
      

  9.   

    C#中,你根本就不能写出两个标签,使得条件判断既符合这个也符合那个。另外,switch只会一次性对变量求值。using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;namespace ConsoleApplication1
    {
        class Program
        {
            static int x = 1;
            static void Main(string[] args)
            {
                switch (foo())
                {
                    case 2:
                        Console.WriteLine("\t" + 2);
                        break;
                    case 3:
                        Console.WriteLine("\t" + 3);
                        break;
                    case 4:
                        Console.WriteLine("\t" + 4);
                        break;
                }
            }
            static int foo()
            {
                x++;
                Console.WriteLine("foo()");
                return x;
            }
        }
    }
      

  10.   

    没叫你在case上打啊,你可以在switch上断点试试
      

  11.   

    1.1楼的回复是告诉你,有些事情其实没必要追究,我们根本关心“回”字到滴有多少种写法,那是“站着穿长衫的人”才会研究的。
    2.swich做为一个基本流程控制语法,甚至在世界上第一个女程序员时代就已经被建立,如果这玩意到现在还有啥问题,那么这100年程序员们都在干啥呢?3.你做个简单实验,你在swich里面做两个的分支。  swich(a)
       case 1:
        break;
        case 1+0:
        break;编译器会告诉你你错了,出现了两个一样的分支,这说明什么?这说明编译器直接优化你的代码,他预先就判定了值,why??答案很简单,他需要保证每个分支值不一样,他需要构建一个hash表,他需要用查表法直接查到分支位置,也就如此而已
      

  12.   

    因为switch不会多次对变量求值,也不允许分支条件是变量,也不允许两个条件相等,也不允许多个标签贯穿(不写break;除非空语句)所以研究顺序是没有意义的。
      

  13.   

    http://msdn.microsoft.com/zh-cn/library/06tc147t(v=vs.80).aspx
      

  14.   

    我也感觉是这样的,因为中间语言看了好像是这样,只不过是switch形成了一个中间表的样子,但是用那个变量值和表中的值比较的时候 好像也是从上往下比较的吧
    =========================================你要明白什么是hash表,什么是内存寻址 就不会这么认为了。 基址+偏移量。也就是说就算他是生成了一个中间表他一不会去全体扫描,他只会直接算出偏移量,然后直接跳转过去就ok
      

  15.   

    直接定位到符合条件的那个case
      

  16.   

    C#中,你根本就不能写出两个标签,使得条件判断既符合这个也符合那个。 嗯,我对这个没疑问,也没问这个
    另外,switch只会一次性对变量求值。嗯,switch是把里面的东西计算一次,然后和其他的进行比较,不会计算多次,这个我以前差过,我想请教大神的是,他拿出switch里面的那个变量后,是不是在底层和每个case里面的值进行了比较? 这种比较又是怎么样的呢,顺序变量从上往下判断么,或者是其他?如果不是和每个case比较,那他是怎么知道对应那个,咋就直接跳转到那个case了呢,底层的东西我真的想了解一下,真心不是像孔乙己一样要知道多个茴香豆的写法,请指教,谢谢
      

  17.   

    嗯,switch打了断点,f11调试的结果是直接跳到对应的case,但是他是怎么知道对应的case呢,我是想知道原理,他没有比较,他怎么知道是哪个case呢
      

  18.   

    1.我想知道更深层次的一些东西,了解某些东西后,会对代码更好的优化,理解上更进一层,和孔乙己是两码事。
    2.我没有质疑这个,我只是想大神指导一下底层的东西
    3.嗯,他保证switch的值是唯一的,这个我同意,“他需要构建一个hash表,他需要用查表法直接查到分支位置:”,嗯,我想问的就是这个查表法,是怎么个查找,怎么就查到这个分支的,没有一个个判断,他早呢么知道是哪个?查找的方式是什么?顺序查找还是其他的,请指教,谢谢。
    4.我只是想多知道点东西,之前我也查过很多相关的帖子,自己也用IL反编译过switch代码,但是还是有点迷糊,所以想请教一下,如果能解惑的话,当然很感谢,如果不能我也不能强求不是
      

  19.   


    楼主的意思不是质疑
    “case加不了断点,f11就直接进入到分支了”这个不是很奇怪吗
    加不了断点,在哪儿判断的
      

  20.   

    不是很懂,你提到的那些不容许,我感觉和 研究顺序没有什么关系,我研究是普通的合格switch,是没有多次对变量求值,也没有设条件为变量,也没有相等的两个条件。 我感觉我理解估计还是不大好,请指教。
      

  21.   

    先判断Switch的值,然后从上往下找到値相同的case 执行下面的语句,如果没有遇到Break则还会进入接下来的Case,所以每个Case里面一般都会加入Break;
      

  22.   

    理论上一个意思,但是逻辑层面上不一样啊 一个是逐个判断,一个是直接获取变量进行判断执行代码行总的来说如果状态非常多就用swich case如果就是true or false 就用if else 这个就是用方便的问题
      

  23.   


    这个不是很好用文字表达,hash表的存储方式并不是使用连续内存存储,他是使用基地址+偏移量存储比 1,3,5 相当于下面的表述swich表 基地址为100;
    则 case 1: 在内存地址100+1的位置存储一个代码段指针
       case 3: 在内存100+3 的位置存储一个代码段指针
       case 5: 在内存100+5 的位置存储一个代码段指针那么如果是参数5进入swich逻辑的话,他并不需要去扫描1,3的地址,他会直接采用100+5去获取内存地址[105]处一个代码段指针,然后直接jmp过去
      

  24.   

    不是的,这点和if...else if...else语句不同
      

  25.   


    嗯,对,他是转到1,3,5对应的内存地址的,我看中间语言就是这样的
    我的问题就是
    “如果是参数5进入swich逻辑的话,他并不需要去扫描1,3的地址”
     那么哪怎么知道是转到1对应的地址呢,还是3对应的地址呢,还是5对应的地址呢?他是不是要先跟前面的1,3,5判断下呢,然后再转到对应的内存地址呢?这个顺序是怎么样的呢?或者说是其他的?
      

  26.   

    写了个简单的控制台程序如下,其反编译的中间语言也在下面,我想问的是 il中 IL_0001行的变量是不是要先和 IL_000d 行的“k”比较,再和IL_001a行的"a"比较,这样顺序比较下来,比较到IL_0027行的"g",发现相等,所以转到 IL_0042 的处理方法呢?我要问的是前面那个比较方法是怎么样的,是不是我理解的按顺序来的,或者说我这样理解是错误的?
     static void Main(string[] args)
            {
                string x="g";
                switch (x)
                {
                    case "k":
                        Console.WriteLine("cccc");
                        break;
                    case "a":
                        Console.WriteLine("cccc");
                        break;
                    case "g":
                        Console.WriteLine("cccc");
                        break;            }
            }       
    .method private hidebysig static void  Main(string[] args) cil managed
    {
      .entrypoint
      // 代码大小       93 (0x5d)
      .maxstack  2
      .locals init (string V_0,
               string V_1)
      IL_0000:  nop
      IL_0001:  ldstr      "g"
      IL_0006:  stloc.0
      IL_0007:  ldloc.0
      IL_0008:  stloc.1
      IL_0009:  ldloc.1
      IL_000a:  brfalse.s  IL_005c
      IL_000c:  ldloc.1
      IL_000d:  ldstr      "k"
      IL_0012:  call       bool [mscorlib]System.String::op_Equality(string,
                                                                     string)
      IL_0017:  brtrue.s   IL_0035
      IL_0019:  ldloc.1
      IL_001a:  ldstr      "a"
      IL_001f:  call       bool [mscorlib]System.String::op_Equality(string,
                                                                     string)
      IL_0024:  brtrue.s   IL_0042
      IL_0026:  ldloc.1
      IL_0027:  ldstr      "g"
      IL_002c:  call       bool [mscorlib]System.String::op_Equality(string,
                                                                     string)
      IL_0031:  brtrue.s   IL_004f
      IL_0033:  br.s       IL_005c
      IL_0035:  ldstr      "cccc"
      IL_003a:  call       void [mscorlib]System.Console::WriteLine(string)
      IL_003f:  nop
      IL_0040:  br.s       IL_005c
      IL_0042:  ldstr      "cccc"
      IL_0047:  call       void [mscorlib]System.Console::WriteLine(string)
      IL_004c:  nop
      IL_004d:  br.s       IL_005c
      IL_004f:  ldstr      "cccc"
      IL_0054:  call       void [mscorlib]System.Console::WriteLine(string)
      IL_0059:  nop
      IL_005a:  br.s       IL_005c
      IL_005c:  ret
    } // end of method Program::Main
      

  27.   

    不好意思上面写错了一句 “发现相等,所以转到 IL_0042 的处理方法呢?”这一句写错了应该改为 “发现相等,所以转到 IL_004f行  的处理方法呢?”另外一点,我发现如果swtich里面传的参数是数字的话,形成的il语言差异很大,而且,如果是数字的话,你不按数字大小顺序来写case的话,中间语言会帮你排序好,然后处理,而且中间语言里也有swtich,这个他又是怎么处理的呢,是不是中间语言到机器语言的时候,又有什么操作,进行了二分算法什么的?这个是另外一个话题,有懂得顺便指教一下,谢谢
      

  28.   

    可以看看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了,所以把这个过程有意隐藏了
      

  29.   


    为什么高手总是这么低调呢,非常感谢您,我以前猜想的就是你这样的,但是不知道原因,看了你说的解释后,我感觉就是这样的,就是官方的不知道是不是有这样的说明,因为不敢肯定就一定是这样的,有些内容你也说了是猜测的,不过你猜测的好像很是那么回事,嗯,暂时先这么理解吧,十分感谢。”jmp dword ptr [eax*4+002B2878h]  
    “ 这个就真心看不懂了
    还有一个疑问,希望能指导一下,是不是switch 的是数字的话,编译成机器码的时候,还进行了2分查找之类的,所以比if什么的速度更快了,或者说就只是像你说的跳转表,执行swtich指令。 
      

  30.   

    case 后面有break的话, 遇到条件成立,执行完毕,break 跳出.如果CASE 后面没有break的话,会逐个比较
      

  31.   


    如果是连续的,就直接switch了,这样最快。如果是离散的,从我的观察,小数据量时是直接if else的,没用什么数据结构,但没试过大量的,不排除用List排序实现的可能,就像大量字符串用Dictionary一样,但据我实验50个case还是用if判断,有可能编译器真没那么智能,也有可能没到编译器认为的阈值。
      

  32.   

    switch(a)
    {
    case 0:fun(0);
    case 1:fun(1)
    case 2:fun(2)
    }如果你会汇编,一看反汇编后的代码就知道是怎么回事了
    编译器为所有的case生成了一个表,里面存有所有case后面的代码的地址。
    根据switch里的值直接转到表里的地址就可以了。
    //下面的代码并不能执行,只是举例说明一下
    address[3]={case_0,case_1,case_2};
    jmp address[a];//跳转到a对应的位置。
    case_0:fun(0);
    case_1:fun(1);
    case_2:fun(2);
      

  33.   


    那他去表里找对应的记录的时候是按顺序找的么,如果是的话,那么和if else也差不多,从上往下找
      

  34.   

    为什么问这个问题呢,是因为我想知道switch和if谁效率高这个问题。百度了一圈后,还是对swtich底层有点迷糊,所以上来提问。个人总结一下:(个人看法)
    如果swtich的是字符串或者字符类型的话
        用if和switch其实效率差不多,if每次都要把字符串取出来和要比较的值比较一下,而switch只是取出来一次,然后和case里面的分别比较就行了,所以在这点上效率上要高那么一点点。
        两者的机制不一样,swtich是把所有case的值统一放到一起形成一个表,然后用要判断的值与他们进行一个个比较,在我看来,这个比较应该是按顺序进行的,如果比较相等的话,则转到对应的处理方法,swtich是case值放一起,处理的方法放一起,而if是每个判断条件后面跟一个处理方法,根据判断的结果来决定是否进入到该处理方法。所以这么来说的话,在这一点上,他们的处理效率应该是差不多的,只不过一个是放到一起一个个判断,一个是判断一个处理一个,但是都是顺序来的。(可以看一下41楼的中间语言,或者自己写个小程序看看中间语言)
    如果swtich的是数字的话
         用if和swtich效率差距就比较大,特别是如果是连续的数字,swtich的中间语言会形成switch( IL_0229, IL_0239, IL_0249),这么样的东西,会将case里面的数字按照顺序排列,这样的话,就可以支持二分查找啦,那么这样的速度绝对是快很多,机制还是和上面说到的机制一样,但是查找方法不一样,所以会比if快很多,而if的处理数字机制和处理字符串的机制差不多,不过不用像字符串一样频繁的去取了。
         如果不是连续的数字的话,也会形成switch( IL_0229, IL_0239, IL_0249)这样的东西,我估计像46楼猜想的那样 ”这个动作是O(1)的,不需要一个一个判断。“  ,所以数字不管是连续的还是不连续的,他就算是按顺序来,也比if那种一个个判断要快上许多。
    以上纯属目前个人推测以及猜想,说的也比较乱,暂时这么想的,如果有错误的地方,还往不吝赐教,谢谢
      

  35.   

      C#我不知道,我只知道C/C++中的switch是如何工作的。最好的方法是看标准,而不是在那里自己臆想,不能想当然。
      C中有段著名的代码,叫Duff's device(达夫设备),代码如下:
    send(to, from, count)
    register short *to, *from;
    register count;
    {
            register n = (count + 7) / 8;
            switch(count % 8) {
            case 0: do {    *to = *from++;
            case 7:         *to = *from++;
            case 6:         *to = *from++;
            case 5:         *to = *from++;
            case 4:         *to = *from++;
            case 3:         *to = *from++;
            case 2:         *to = *from++;
            case 1:         *to = *from++;
                    } while(--n > 0);
            }
    }
      这段代码很多第一次看到的人都会晕吧?
      对于语法,建议你可以看看《C语言参考手册(原书第5版)》,这本书有中文版的,虽然译得很勉强,但是至少对于switch语句我是看明白了。
      以前,我以为像:
    /*代码1*/
    switch(a1+a2*a3)
    {
    case 3:bbb;break;
    case 4:ccc;break;
    case 5:ddd;break;
    default:eee;break;
    }
    将会被编译成这样的伪代码:
    tmp1=a1+a2*a3;
    jmp case3
    case3:
    cmp tmp1,3
    jnz case4
    bbb;
    jmp endofswitch
    case4:
    cmp tmp1,4
    jnz case5
    ccc;
    jmp endofswitch
    case5:
    cmp tmp1,5
    jnz default
    ddd;
    jmp endofswitch
    default:
    eee;
    jmp endofswitch
    endofswitch:
      这就像if else if else了。不过这并不正确,因为如果将源代码改成:
    /*代码2*/
    switch(a1+a2*a3)
    {
    case 3:bbb;
    case 4:ccc;
    case 5:ddd;break;
    default:eee;break;
    }
      按照C语言的说法,假如case 3被匹配,那么除了bbb;被执行外,还将“掉落”执行ccc;ddd;直到ddd;后的break;才跳出到switch语句后。但由于刚才的编译伪代码将判断放在了源代码case标签出现的地方,那么除了在break处编译成转到switch结束处之外,还要在所有没有break语句的地方,放一个跳过下一处case判断的跳转,代码实在是太冗长了。
    其实代码1的编译后伪代码大约是这样的:
    tmp1=a1+a2*a3;
    cmp tmp1,3
    jz case3
    cmp tmp1,4
    jz case4
    cmp tmp1,5
    jz case5
    jmp default
    case3:
    bbb;
    jmp endofswitch
    case4:
    ccc;
    jmp endofswitch
    case5:
    ddd;
    jmp endofswitch
    default:
    eee;
    endofswitch:
      而这种形式下,只要没有break,就等于去掉了相应的jmp endofswitch。
      由于C/C++对case后能出现的东西限制很严,只能是编译时静态求值的一些简单的内置类型直接量(不能是字符串),且具体的实现将可能对case的最多个数有限制,以方便地做成一张跳转表。比如:
    switch(MESSAGE_CODE)
    case 0: ...
    case 2: ...
    case 3: ...
    ...
    case 1023: ...
    那么编译器完全可以做出一个0..1023的跳转数组,并对没有设置选项的case 1,设为跳到switch之外,因此编译后代码就更短了:
    addr_arr[1024]={case0,endofswitch or default,case2,case 3... case 1023};
    tmp1=MESSAGE_CODE;
    if tmp1 not in 0..1023 then goto endofswitch(or default address)
    jmp addr_arr[MESSAGE_CODE];
    case 0:
      ...;jmp endofswitch or default
    case 2:
      ...;jmp endofswitch or default
    case 3:
    ...
    endofswitch or default:
      即使case值的集合比较离散,不适合做成数组跳转表,C仍然可以将所有选项做成二叉树,通过二分法查找,以缩短比较的总次数。这也是我以前看过一些编译或反汇编出来的结果非常难懂的原因。
      C程序的switch往往除了判断int型的代码外,往往也判断char,比如对命令行程序选项的解释器代码,因此这些强制规则都是历史的产物了,与UNIX时代语言设计者想让switch发挥的作用密切相关。
    如今,虽然不指望switch语句会像Ada的case、SQL的CASE或VB的Select Case那样灵活,至少也得容许case中出现字符串吧?C++觉得字符串的比较还是个“大活儿”,对库函数是有复杂的依赖(比如,是char还是wchar_t的字符串?),因此与C一致,它仍然不允许。Java和C#呢?算是在效率与灵活性方面取了个折中,这也是这几种语言各自定位造成的。
      回到文章开始的Duff's device,《C语言参考手册》中介绍了case是与其外最内层的switch相匹配的。
      default也可以出现在所有的case之前或它们之间(因此也可以从default往其他case上“掉落”),这并不影响编译器识别和跳转,default虽然总是所有case都没成功后的第一去处,但它的代码也可以在case的前面:
    switch(a)
    {
    default: aaa;
    case 'b':bbb;
    case 'c':ccc;break;
    case 'd':ddd;break;
    case 'e':eee;
    }
      在C++中,要注意如果某case代码段中有构造发生,那么一定要将其包在{}块语句中。因为如果没有放在{}中,则其作用域在switch的一对{}之内,由于switch之后会在各case及default中跳转,对象的析构全部放在switch结尾,其构造却有可能被跳过,如:
    switch(i)
    {
    case 1:
      break;//跳过了构造却仍然要执行析构
    case 2:
      SomeClassType a;//a在此构造
      break;
    case 3:
      break;//跳过了构造却仍然要执行析构
    //a在此析构
    }
      

  36.   

    补充一下,除default之外,其它的保证逻辑顺序为按case出现的顺序来做判断。
      

  37.   


    如果是连续的,就直接switch了,这样最快。如果是离散的,从我的观察,小数据量时是直接if else的,没用什么数据结构,但没试过大量的,不排除用List排序实现的可能,就像大量字符串用Dictionary一样,但据我实验50个case还是用if判断,有可能编译器真没那么智能,也有可能没到编译器认为的阈值。
    [/Quote]
    刚刚又仔细看了一下,我这里搞错了,确实是2分查找的,但没用什么其他的工具类,是直接if的,先判断中间的值,再往2边走。
    像这个
    switch(a)
    {
    case 100:
    case 200:
    case 300:
    case 400:
    case 500:
    case 600:
    }
    il里是这样的
    if(a>300)
    {
       if(a==100){}
       else if(a==200){}
       else if(a==300){}
    }else
    {
       if(a==400){}
       else if(a==500){}
       else if(a==600){}
    }可能我这边的数据量少,只2分了一步
      

  38.   


    这里没有什么只取一下的概念,字符串比较的时候都是在调用string.Equals()函数
    前面说过字符串量大的时候会用hashtable,这个是近似于o(1)的,比if的o(n)要快
    switch( IL_0229, IL_0239, IL_0249)是绝对的o(1)的,过程就是一个数组的随机存取,像#36楼所说的不是连续的就不能用switch( IL_0229, IL_0239, IL_0249),只能用2分查找,O(log(n))的,但还是要比自己if强总的来说,用switch要比if好,不管是效率还是可读性。从根本上看switch的优势是因为它对要比较的表达式做了较多的限制(只能是编译时可知的,类型必须是int或string)从而编译器能够有针对性的优化,而 if因为 可变性较大没法做优化
      

  39.   

    我对这个问题也有兴趣,我随便写了个if-else和switch语句进行对比,下面是C++源码和汇编代码,从汇编代码看,if-else是逐一判断的没有争议,但是,switch居然也是逐一进行判断的,没有对代码进行任何优化!这是vc6反汇编出来的代码,从这段代码
    004015BF   mov         eax,dword ptr [ebp-0Ch]
    004015C2   mov         dword ptr [ebp-10h],eax
    004015C5   cmp         dword ptr [ebp-10h],5
    004015C9   je          main+79h (004015d9)
    004015CB   cmp         dword ptr [ebp-10h],6
    004015CF   je          main+82h (004015e2)
    004015D1   cmp         dword ptr [ebp-10h],7
    004015D5   je          main+8Bh (004015eb)
    004015D7   jmp         main+94h (004015f4)可以看出,switch仍然是和每个分支的条件值进行比较,一旦je相等,则跳到相应分支的地址去执行分支代码,而并没有所谓的hash表,通过case值直接hash得到分支的地址。我唯一看到if-else和switch语句有区别的地方就是,if是直接从条件变量的地址取值出来和条件进行判断,而switch要开辟一个空间拷贝一个条件变量,然后再去新的值和case的值逐一比较,代码在这里
    004015BF   mov         eax,dword ptr [ebp-0Ch]
    004015C2   mov         dword ptr [ebp-10h],eax
    int main()
    {    int a = 5;
    int b = 6;
    int c = 7; if ( a == 5 )
    {
    c = 5*a;
    }
    else if ( a == 6 )
    {
    c = 6*a;
    }
    else
    {
    c = 7*a;
    } c = 6;
    switch ( c )
    {
    case 5:
    b = 5;
    break;

    case 6:
    b = 6;
    break; case 7:
    b = 7;
    break; default:
    b = 8;
    break;
    }    cout<<a<<b<<c<<endl; return 0;
    }7:        int a = 5;
    00401578   mov         dword ptr [ebp-4],5
    8:        int b = 6;
    0040157F   mov         dword ptr [ebp-8],6
    9:        int c = 7;
    00401586   mov         dword ptr [ebp-0Ch],7
    10:
    11:       if ( a == 5 )
    0040158D   cmp         dword ptr [ebp-4],5
    00401591   jne         main+3Eh (0040159e)
    12:       {
    13:           c = 5*a;
    00401593   mov         eax,dword ptr [ebp-4]
    00401596   imul        eax,eax,5
    00401599   mov         dword ptr [ebp-0Ch],eax
    14:       }
    15:       else if ( a == 6 )
    0040159C   jmp         main+58h (004015b8)
    0040159E   cmp         dword ptr [ebp-4],6
    004015A2   jne         main+4Fh (004015af)
    16:       {
    17:           c = 6*a;
    004015A4   mov         ecx,dword ptr [ebp-4]
    004015A7   imul        ecx,ecx,6
    004015AA   mov         dword ptr [ebp-0Ch],ecx
    18:       }
    19:       else
    004015AD   jmp         main+58h (004015b8)
    20:       {
    21:           c = 7*a;
    004015AF   mov         edx,dword ptr [ebp-4]
    004015B2   imul        edx,edx,7
    004015B5   mov         dword ptr [ebp-0Ch],edx
    22:       }
    23:
    24:       c = 6;
    004015B8   mov         dword ptr [ebp-0Ch],6
    25:       switch ( c )
    26:       {
    004015BF   mov         eax,dword ptr [ebp-0Ch]
    004015C2   mov         dword ptr [ebp-10h],eax
    004015C5   cmp         dword ptr [ebp-10h],5
    004015C9   je          main+79h (004015d9)
    004015CB   cmp         dword ptr [ebp-10h],6
    004015CF   je          main+82h (004015e2)
    004015D1   cmp         dword ptr [ebp-10h],7
    004015D5   je          main+8Bh (004015eb)
    004015D7   jmp         main+94h (004015f4)
    27:       case 5:
    28:           b = 5;
    004015D9   mov         dword ptr [ebp-8],5
    29:           break;
    004015E0   jmp         main+9Bh (004015fb)
    30:
    31:       case 6:
    32:           b = 6;
    004015E2   mov         dword ptr [ebp-8],6
    33:           break;
    004015E9   jmp         main+9Bh (004015fb)
    34:
    35:       case 7:
    36:           b = 7;
    004015EB   mov         dword ptr [ebp-8],7
    37:           break;
    004015F2   jmp         main+9Bh (004015fb)
    38:
    39:       default:
    40:           b = 8;
    004015F4   mov         dword ptr [ebp-8],8
    41:           break;
    42:       }
    43:
    44:       cout<<a<<b<<c<<endl;
    004015FB   push        offset @ILT+195(std::endl) (004010c8)