试图还原老师讲课的思路。
Switch statements
一个例子:
很多人会认为switch是decision trees,实际上二者不一样,决策树是一个一个case判断执行;switch当条件不满足时就不会执行,直到遇到一个满足条件的case就开始顺序往下执行,即使不匹配的case也会被执行。
也有人认为switch和if是等价的,其实不然。case后面是只能跟常量(const value)的,编译时会对 switch 进行优化,根据 case 标签后面的常量值,生成跳转表,只经过少数次数的比较,就可以跳到对应标签下面。所以,标签也是不能重复的。如果允许变量,switch 就退化成一连串的 if else, 对于一个数据也只能从头到尾地进行比较,也就失去了 switch 的意义。跳转表和逐个比较,这两种方式的复杂度差很多。
然后我们来看上面的例子,这里面包含了case的几种情形:
1.顺序往下,都有break:1,2,3
2.多个标签:5&6
3.落空的case:2
4.缺失的case:4
跳转表jump table
跳转表其实是一个指针数组。Code block与跳转表里的指针一一对应。
对于情形1:顺序往下,都有break:自然是一个指针对应一个code block,执行完return。
对于情形2:多个标签:多个指针指向同一个code block。
对于情形3:落空的case:会执行它对应的code block,但是会继续执行后面。
对于情形4:缺失的case:跳转表里没有其指针,当然也没有相应的code block。
那么这些case是怎样和指针数组的index相对应的呢?
还是说上面的例子,case 1,2 ,3分别是index 0, 1,2,case 4缺失,就指向default case,case 5,6重复了,就都是index3,default就是default标签(可能有误)。
case最高是6,这样只要x的值大于6的话就直接进入default。一个指针是4字节,4*%eax就是所需指针在的地址,
下面我们看看跳转表的结构:
每一个target需要4字节;基地址是.L4。
1.直接跳转:jmp .L2 直接跳转到label .L2
2.非直接跳转:jmp *.L4(,%eax,4) 跳转表的头是.L4,标签与头的距离时4的倍数,有效地址是.L4 + eax*4 (0 ≤ x ≤ 6)
对应关系如下:
从这张图我们可以看出x的值是从0开始的,缺失的0和4都是指向default的,标签是.L8;case 1 2 3是正常的,分别对应标签.L3,.L5.L9;case 5 6都指向标签.L7。另外,switch完成则跳转到标签.L2。
然后我们看看code blo