C语言7 switch语句为什么高效

C语言7 switch语句为什么高效

switch语句的定义

语法

switch(表达式)
{
    case 常亮表达式1:
        语句;
        break;
    case 常亮表达式:
        语句;
        break;
    case 常亮表达式:
        语句;
        break;
     ......
    default:
        语句;
        break;
}

需要注意的点

  1. 表达式结束不能使浮点数
  2. case后的值不能一样
  3. case后的值必须是常量
  • break:
  • break非常重要,当执行到一个分支后 如果没有break就会继续向下执行,遇到break才跳出switch语句
  • default 语句与位置无关,但是当default写在其他条件的前面时。如果没有break;,就会向下继续匹配

Switch语句与 if..else语句的区别:

  1. switch语句只能进行等值判断,而if..else可以进行区间判断
  2. switch语句的执行效率远远高于if..else 在分支条件比较多的情况下,这种趋势愈发明显

观察switch语句的反汇编,看看switch语句为啥效率高

为啥switch比if..else效率高

游戏中的switch语句

switch(x)
{
   case 1:
       printf("A \n");
       break;
   case 2:
       printf("B \n");
       break;
   case 3:
       printf("C \n");
       break;
   default:
       printf("default \n");
       break;
}

编译后反汇编代码

11:        switch(x)
12:    {
00401038 8B 45 08             mov         eax,dword ptr [ebp+8]
0040103B 89 45 FC             mov         dword ptr [ebp-4],eax
0040103E 83 7D FC 01          cmp         dword ptr [ebp-4],1
00401042 74 0E                je          MyPrint+32h (00401052)
00401044 83 7D FC 02          cmp         dword ptr [ebp-4],2
00401048 74 17                je          MyPrint+41h (00401061)
0040104A 83 7D FC 03          cmp         dword ptr [ebp-4],3
0040104E 74 20                je          MyPrint+50h (00401070)
00401050 EB 2D                jmp         MyPrint+5Fh (0040107f)
13:       case 1:
14:           printf("A \n");
00401052 68 30 00 42 00       push        offset string "A \n" (00420030)
00401057 E8 B4 00 00 00       call        printf (00401110)
0040105C 83 C4 04             add         esp,4
15:           break;
0040105F EB 2B                jmp         MyPrint+6Ch (0040108c)
16:       case 2:
17:           printf("B \n");
00401061 68 2C 00 42 00       push        offset string "B \n" (0042002c)
00401066 E8 A5 00 00 00       call        printf (00401110)
0040106B 83 C4 04             add         esp,4
18:           break;
0040106E EB 1C                jmp         MyPrint+6Ch (0040108c)
19:       case 3:
20:           printf("C \n");
00401070 68 28 00 42 00       push        offset string "C \n" (00420028)
00401075 E8 96 00 00 00       call        printf (00401110)
0040107A 83 C4 04             add         esp,4
21:           break;
0040107D EB 0D                jmp         MyPrint+6Ch (0040108c)
22:       default:
23:           printf("default \n");
0040107F 68 1C 00 42 00       push        offset string "default \n" (0042001c)
00401084 E8 87 00 00 00       call        printf (00401110)
00401089 83 C4 04             add         esp,4
24:           break;
25:    }
26:   }

区别

当调教比较少的时候 没啥区别 。但是当条件比较多的时候:


11:        switch(x)
12:    {
0040B818 8B 45 08             mov         eax,dword ptr [ebp+8]
0040B81B 89 45 FC             mov         dword ptr [ebp-4],eax
0040B81E 8B 4D FC             mov         ecx,dword ptr [ebp-4]
0040B821 83 E9 01             sub         ecx,1
0040B824 89 4D FC             mov         dword ptr [ebp-4],ecx
0040B827 83 7D FC 03          cmp         dword ptr [ebp-4],3
0040B82B 77 46                ja          $L539+0Fh (0040b873)
0040B82D 8B 55 FC             mov         edx,dword ptr [ebp-4]
0040B830 FF 24 95 91 B8 40 00 jmp         dword ptr [edx*4+40B891h]
13:       case 1:
14:           printf("A \n");
0040B837 68 34 0F 42 00       push        offset string "A \n" (00420f34)
0040B83C E8 CF 58 FF FF       call        printf (00401110)
0040B841 83 C4 04             add         esp,4
15:           break;
0040B844 EB 3A                jmp         $L539+1Ch (0040b880)
16:       case 2:
17:           printf("B \n");
0040B846 68 30 00 42 00       push        offset string "B \n" (00420030)
0040B84B E8 C0 58 FF FF       call        printf (00401110)
0040B850 83 C4 04             add         esp,4
18:           break;
0040B853 EB 2B                jmp         $L539+1Ch (0040b880)
19:       case 3:
20:           printf("C \n");
0040B855 68 2C 00 42 00       push        offset string "C \n" (0042002c)
0040B85A E8 B1 58 FF FF       call        printf (00401110)
0040B85F 83 C4 04             add         esp,4
21:           break;
0040B862 EB 1C                jmp         $L539+1Ch (0040b880)
22:       case 4:
23:           printf("D \n");
0040B864 68 28 00 42 00       push        offset string "D \n" (00420028)
0040B869 E8 A2 58 FF FF       call        printf (00401110)
0040B86E 83 C4 04             add         esp,4
24:           break;
0040B871 EB 0D                jmp         $L539+1Ch (0040b880)
25:       default:
26:           printf("default \n");
0040B873 68 1C 00 42 00       push        offset string "default \n" (0042001c)
0040B878 E8 93 58 FF FF       call        printf (00401110)
0040B87D 83 C4 04             add         esp,4
27:           break;
28:    }
29:   }

我们发现 生成一张内存表。
switch通过算法,直接一步算出地址 从表中找到需要跳转的地址

大表和小表

当生成的函数跳转地址表 每个成员有4个字节的时候 我们称之为 大表

总结:

  1. 即没有大表也没有小表:
    • case 项小于等于3项
    • case最大值和最小值差值>=255
  2. 有大表没小表:
    • case项大于3项并且大表项空隙小于等于6个
  3. 有大表有小表
    • case项大于3项并且大表项空隙大于6个并且case最大最小差值<255
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,701评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,649评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 166,037评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,994评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,018评论 6 395
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,796评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,481评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,370评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,868评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,014评论 3 338
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,153评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,832评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,494评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,039评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,156评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,437评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,131评论 2 356

推荐阅读更多精彩内容