让我们看下面的示例:
switch-case控制语句维护一个跳转表,该跳转表不能通过一系列if-else实现. 在上面的示例中,它是标签L7标记
值得纪念的地方.
跳转表方法的总体思路是这样的
使用case语句中的最大值减去最小值来找到一个间隔,这里是106-100 = 6,即0到6有7种可能的情况,那么编译器
为切换案例控件分配一个长度为7的数组c语言对应汇编语句,然后编译器将查询存在的案例,并填写数组中的相应位置
案例的地址(即L3,L4,L9,L6),如果没有对应的案例,则填写与默认值相对应的地址(即L2). 在执行结束时,只要
在这种情况下,使用switch参数(即n)减去最小值,您可以获得一个索引,您可以使用该索引直接跳转到相应的案例语言
句子. 这比if-else更有效.
以下是上述汇编代码的详细分析:
swithcase_asm:
pushl%ebp;用于功能管理
mov %% esp,%ebp;用于功能管理
mov 8(%ebp),%eax;得到x
mov 12(%ebp),edx%;得到n
subl $ 100,%edx;用n-100保存到edx%
cmpl $ 6,%edx;比较%edx和6
ja .L2;如果edx%的值大于6,则直接跳转到默认标签L2
jmp * .L7(,%edx,4);如果小于或等于6,则在索引表中搜索后跳转到相应的情况
.section .rodata
.align 4
.align 4
.L7 :;跳转表
.long .L3
.long .L2
.long .L4
.long .L9
.long .L6
.long .L2
.long .L6
.text
.L2 : ;默认
移动$ 0,%eax
jmp .L8
.L3 :;案例100
回音(%eax,%eax,2),%edx
回音(%eax,%edx,4),%eax
jmp .L8
.L4 :;案例102
addl $ 10,%eax
.L9 :;案例103
addl $ 11,eax
jmp .L8
.L6 : ;案例104,106
eullull eax,%eax
.L8:
popl%ebp
ret
但是,如果使用跳转表方法,那么如果case语句中的最大值和最小值之间的差异较大,则会出现内存消耗问题,
因此它将消耗大量内存. 接下来,让我们看看编译器如何处理这种情况:
我们将案例106更改为案例1106. 让我们再次看一下汇编代码. 没有跳转表的痕迹. 是的,你猜对了. 在这种情况下,编译器仍然使用if-else控制方法. . 但是它也通过二进制搜索(上面的红色矩形包围的区域)进行了优化.
然后通过上面的汇编分析c语言对应汇编语句,我们可以看到,在编写switch-case结构时,为了使程序运行更快,应避免间隔间隙
数字太大.
本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/jisuanjixue/article-163243-1.html