5.4 switch的真相(1)
switch是比较常用的多分支结构,使用起来也非常方便,并且效率上也高于if…else if多分支结构。同样是多分支结构,switch是如何进行比较并选择分支的?它和if…else if的处理过程一样吗?下面我们通过简单的switch多分支结构慢慢揭开它的神秘面纱。编写case语句块不超过3条的switch多分支结构,如代码清单5-8所示。
代码清单5-8 switch 转换if else的 C++(www.cppentry.com)代码
- //略去无关代码
- int nIndex = 1;
- scanf("%d", &nIndex);
- switch(nIndex) {
- case 1: printf("nIndex == 1"); break;
- case 3: printf("nIndex == 3"); break;
- case 100: printf("nIndex == 100") ;break;
- }
代码清单5-8中的case语句块只有3条,也就是只有3条分支。if…else if的处理方案是分别进行比较,得到选择的分支,并跳转到分支语句块中。switch也会使用同样的方法进行分支处理吗?下面通过代码清单5-9进行分析和验证。
代码清单5-9 switch 转换if else —Debug版
- switch(nIndex) { // 源码对比
- 0040DF00 mov ecx,dword ptr [ebp-4]
- ; 取出变量nIndex的值并放到ecx中,再将ecx放入临时变量 ebp - 8中
- 0040DF03 mov dword ptr [ebp-8],ecx
- ; 将临时变量和1进行比较
- 0040DF06 cmp dword ptr [ebp-8],1
- ; 条件跳转比较,等于1则跳转到地址0x0040DF1A处
- 0040DF0A je SwitchIf+4Ah (0040df1a)
- ; 将临时变量和3比较
- 0040DF0C cmp dword ptr [ebp-8],3
- ; 条件跳转比较,等于3则跳转到地址0x0040DF29处
- 0040DF10 je SwitchIf+59h (0040df29)
- ; 将临时变量和100比较
- 0040DF12 cmp dword ptr [ebp-8],64h
- ; 条件跳转比较,等于100则跳转到地址0x0040DF38处
- 0040DF16 je SwitchIf+68h (0040df38)
- 0040DF18 jmp SwitchIf+75h (0040df45)
- case 1: // 源码对比
- printf("nIndex == 1"); // 源码对比
- 0040DF1A push offset string "nIndex == 1" (00421024)
- 0040DF1F call printf (004014b0)
- 0040DF24 add esp,4
- break; // 源码对比
- 0040DF27 jmp SwitchIf+75h (0040df45)
- case 3: // 源码对比
- printf("nIndex == 3"); // 源码对比
- 0040DF29 push offset string "nIndex == 3" (004210d8)
- 0040DF2E call printf (004014b0)
- 0040DF33 add esp,4
- break; // 源码对比
- 0040DF36 jmp SwitchIf+75h (0040df45)
- case 100: // 源码对比
- printf("nIndex == 100"); // 源码对比
- 0040DF38 push offset string "nIndex == 100" (0042004c)
- 0040DF3D call printf (004014b0)
- 0040DF42 add esp,4
- break; }} // 源码对比
- 0040DF45 pop edi
从对代码清单5-9的分析中得出,switch语句使用了3次条件跳转指令,分别与1、3、100进行了比较。如果比较条件成立,则跳转到对应的语句块中。这种结构与if…else if多分支结构非常相似,但仔细分析后发现,它们之间有很大的区别。先看看if…else if结构产生的代码,如代码清单5-10所示。
代码清单5-10 if…else if结构—Debug版
- if (nIndex == 1) { // 源码对比
-
- ; if比较跳转
- 004011C5 cmp dword ptr [ebp-4],1
- 004011C9 jne SwitchIf+8Ah (004011da)
- printf("nIndex == 1"); // 源码对比
- ; if语句块
- 004011CB push offset string "nIndex == 1" (00423080)
- 004011D0 call printf (00401680)
- 004011D5 add esp,4
- }else if (nIndex == 3) // 源码对比
- ; else跳转
- 004011D8 jmp SwitchIf+0B2h (00401202)
- ; if比较跳转
- 004011DA cmp dword ptr [ebp-4],3
- 004011DE jne SwitchIf+9Fh (004011ef)
- {printf("nIndex == 3"); // 源码对比
- ; if语句块
- 004011E0 push offset string "nIndex == 3" (0042304c)
- 004011E5 call printf (00401680)
- 004011EA add esp,4
- }else if (nIndex == 3) // 源码对比
- ; else 跳转
- 004011ED jmp SwitchIf+0B2h (00401202)
- ; if比较跳转
- 004011EF cmp dword ptr [ebp-4],3
- 004011F3 jne SwitchIf+0B2h (00401202)
- { printf("nIndex == 100"); // 源码对比
- ; if语句块
- 004011F5 push offset string "nIndex == 100" (00423090)
- 004011FA call printf (00401680)
- 004011FF add esp,4
- }
- // 结尾