猿问

switch case的跳转原理?

当有很多个case时,switch是怎样做到只要少数比较(只要1次?)就得出结果的?
就算有个跳转表也是需要经过多次的比较才可以找到相应的位置的不是吗?毕竟是dumb compute,当没有给一个明确的指令时,只有通过不断的比较才可以得到结果。
例如SQL的索引,索引的原理和switch差不多吧,只是原理到底是什么?

白衣染霜花
浏览 999回答 1
1回答

呼如林

我们可以直接通过汇编代码来看:void bob(){&nbsp; &nbsp; int a = 1;&nbsp; &nbsp; switch(a)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; case 1:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; std::cout<<"case 1"<<std::endl; break;&nbsp; &nbsp; &nbsp; &nbsp; case 2:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; std::cout<<"case 2"<<std::endl; break;&nbsp; &nbsp; &nbsp; &nbsp; case 3:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; std::cout<<"case 3"<<std::endl; break;&nbsp; &nbsp; &nbsp; &nbsp; default:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; std::cout<<"default case"<<std::endl;&nbsp;&nbsp; &nbsp; }}汇编其中关键代码如下:可以看到case实际的比较顺序是2->3->1, 并不是代码的编写顺序:0000000000400846 <_Z3bobv>:&nbsp; 400846:>..55&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;>..push&nbsp; &nbsp;%rbp&nbsp; 400847:>..48 89 e5&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;>..mov&nbsp; &nbsp; %rsp,%rbp&nbsp; 40084a:>..48 83 ec 10&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; >..sub&nbsp; &nbsp; $0x10,%rsp&nbsp; 40084e:>..c7 45 fc 01 00 00 00 >..movl&nbsp; &nbsp;$0x1,-0x4(%rbp)&nbsp; 400855:>..8b 45 fc&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;>..mov&nbsp; &nbsp; -0x4(%rbp),%eax&nbsp; //先比较是否等于2, 如果是,则跳转到0x400885指令地址, 即case的输出语句;&nbsp; 400858:>..83 f8 02&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;>..cmp&nbsp; &nbsp; $0x2,%eax&nbsp; 40085b:>..74 28&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; >..je&nbsp; &nbsp; &nbsp;400885 <_Z3bobv+0x3f>&nbsp; //否则,继续比较是否等于3,&nbsp; 40085d:>..83 f8 03&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;>..cmp&nbsp; &nbsp; $0x3,%eax&nbsp; 400860:>..74 41&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; >..je&nbsp; &nbsp; &nbsp;4008a3 <_Z3bobv+0x5d>&nbsp; //最后比较是否等于1&nbsp; 400862:>..83 f8 01&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;>..cmp&nbsp; &nbsp; $0x1,%eax&nbsp; 400865:>..75 5a&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; >..jne&nbsp; &nbsp; 4008c1 <_Z3bobv+0x7b>&nbsp; 400867:>..be d4 09 40 00&nbsp; &nbsp; &nbsp; &nbsp;>..mov&nbsp; &nbsp; $0x4009d4,%esi&nbsp; 40086c:>..bf 60 10 60 00&nbsp; &nbsp; &nbsp; &nbsp;>..mov&nbsp; &nbsp; $0x601060,%edi&nbsp; 400871:>..e8 9a fe ff ff&nbsp; &nbsp; &nbsp; &nbsp;>..callq&nbsp; 400710 <_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_>&nbsp; 400876:>..be 30 07 40 00&nbsp; &nbsp; &nbsp; &nbsp;>..mov&nbsp; &nbsp; $0x400730,%esi&nbsp; 40087b:>..48 89 c7&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;>..mov&nbsp; &nbsp; %rax,%rdi&nbsp; 40087e:>..e8 9d fe ff ff&nbsp; &nbsp; &nbsp; &nbsp;>..callq&nbsp; 400720 <_ZNSolsEPFRSoS_E@plt>&nbsp; 400883:>..eb 58&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; >..jmp&nbsp; &nbsp; 4008dd <_Z3bobv+0x97>&nbsp; 400885:>..be db 09 40 00&nbsp; &nbsp; &nbsp; &nbsp;>..mov&nbsp; &nbsp; $0x4009db,%esi&nbsp; 40088a:>..bf 60 10 60 00&nbsp; &nbsp; &nbsp; &nbsp;>..mov&nbsp; &nbsp; $0x601060,%edi&nbsp; 40088f:>..e8 7c fe ff ff&nbsp; &nbsp; &nbsp; &nbsp;>..callq&nbsp; 400710 <_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_>&nbsp; 400894:>..be 30 07 40 00&nbsp; &nbsp; &nbsp; &nbsp;>..mov&nbsp; &nbsp; $0x400730,%esi&nbsp; 400899:>..48 89 c7&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;>..mov&nbsp; &nbsp; %rax,%rdi&nbsp; 40089c:>..e8 7f fe ff ff&nbsp; &nbsp; &nbsp; &nbsp;>..callq&nbsp; 400720 <_ZNSolsEPFRSoS_E@plt>&nbsp; 4008a1:>..eb 3a&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; >..jmp&nbsp; &nbsp; 4008dd <_Z3bobv+0x97>&nbsp; 4008a3:>..be db 09 40 00&nbsp; &nbsp; &nbsp; &nbsp;>..mov&nbsp; &nbsp; $0x4009db,%esi&nbsp; 4008a8:>..bf 60 10 60 00&nbsp; &nbsp; &nbsp; &nbsp;>..mov&nbsp; &nbsp; $0x601060,%edi&nbsp; 4008ad:>..e8 5e fe ff ff&nbsp; &nbsp; &nbsp; &nbsp;>..callq&nbsp; 400710 <_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_>&nbsp; 4008b2:>..be 30 07 40 00&nbsp; &nbsp; &nbsp; &nbsp;>..mov&nbsp; &nbsp; $0x400730,%esi&nbsp; 4008b7:>..48 89 c7&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;>..mov&nbsp; &nbsp; %rax,%rdi&nbsp; 4008ba:>..e8 61 fe ff ff&nbsp; &nbsp; &nbsp; &nbsp;>..callq&nbsp; 400720 <_ZNSolsEPFRSoS_E@plt>&nbsp; 4008bf:>..eb 1c&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; >..jmp&nbsp; &nbsp; 4008dd <_Z3bobv+0x97>&nbsp; 4008c1:>..be e2 09 40 00&nbsp; &nbsp; &nbsp; &nbsp;>..mov&nbsp; &nbsp; $0x4009e2,%esi&nbsp; 40092c:&nbsp; &nbsp; &nbsp; &nbsp;c9&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; leaveq&nbsp;&nbsp; 40092d:&nbsp; &nbsp; &nbsp; &nbsp;c3&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; retq&nbsp; &nbsp;至于为什么是这个顺序,没有研究过,这是编译器层面的处理了,可以一起学习下,
随时随地看视频慕课网APP

相关分类

JavaScript
我要回答