1.swtich(4分支以上)所形成的跳转表是在编译过程中实现的,使得其效率高于if..else语句。
在编译过程中程序生成了一个数组,数组中存储的是要跳转到某case中的地址,缺省的都以deflaut或者switch结尾的地址代替。运行过程中,先判断该值有没有超出范围,否则直接跳出,然后再类似数组中随机访问直接跳转到某case语句进行执行,无需再进行其他比较。
(1)如果之间case后的数值之间跨度很大,是否要从头至尾生成,此很费空间。跳转表何时形成?在哪里存储,数据段?编译时形成,存储数据段,这样则会在装载时直接将其装入,然后进行读取。
(2)该表是在编译过程中生成的,在程序执行过程中,先进行比较,然后进行跳转,直接跳转的原因是形成的数组,而输入的整型数据刚好对应于其下标,将下标乘以size直接跳转至目标进行运算。
case语句的数目及case后的整型数据之间的跨度使得对其进行优化的方案不同。
case语句的整型数值跨度大难已形成跳转表。
case语句中的整型如果跨度不大于六且四分之以上的,形成跳转表。
不超过4分支if语句比较。通过代码中的比较顺序逐个比较,遇到符合条件的就进入执行代码。Switch的比较跳转指令在一起,而执行代码在一起,两者分开。
而if...else语句没有将其分开,先进行if中的条件判断,如果不符合条件则跳转,符合条件则执行该过程代码块。
所以switch如果没有break则会从其开始到结束全部执行。两者通过比较,其都需要进行多次比较才能找到符合条件的代码块,所以其效率相似。
如果是线性的,则是先将“比较码”取出,减去case中的最小值,使得其与数组的下标相符合。其中两点:1.数组下标是从零开始的。2.在编译优化过程中形成跳转表,是要将其中case后的数值进行从小到大排列,使之形成数组形式的顺序。然后将所得的差值与数组中的最大值相比较,数组中的最大值是case中最大的标号减去最小的。如果不大于该数则进行数组的性质随机访问跳转。否则直接跳出去或者调到deflaut中去。如果case中最小值为零是就不用调整下标。(当输入的数值为零或者一个负数时,同样会大于6)
注意其中的整型是有符号的,在其中是以补码形式进行访问的,如果和常数进行比较,则是以什么样的数字格式进行比较。
对于没有case对应的数值,编译器以switch的结束地址或者deflault语句块的首地址填充对应的表格项。
如果每两个case值之间的差值小于等于六。并且case语句数大于等于4,编译器中就会形成这种线性结构。
难以形成跳转表的switch
当两个case值得间隔较大时,如果进行填充,则会造成极大的浪费。对于非线性的switch结构,有索引表方法和树优化。