switch语句中的default位置可以随意放,一开始我想不通,就看了下简单反汇编的,发现原来只是靠default的标记,程序执行时先测试表达式是否满足某个case,若都不满足就跳到default去执行。本人目前还没进军反汇编界,请大牛不要取笑。
下面以两个简单的例子说明:
1)
main()
{ int a = 0; int o = 0; a = 4; switch(a) { case 1: o = 10; printf("%d\n",o); case 2: o = 20; printf("%d\n",o); default: o = 100; printf("%d\n",o); case 3: o = 30; printf("%d\n",o); case 4: o = 40; printf("%d\n",o); }}
这样反汇编出来的是:
switch(a)
{
0040D79D mov eax,dword ptr [ebp-4] ;eax = a
0040D7A0 mov dword ptr [ebp-0Ch],eax ;[ebp-0Ch] = a0040D7A3 mov ecx,dword ptr [ebp-0Ch] ;ecx = a0040D7A6 sub ecx,1 ;ecx -= 10040D7A9 mov dword ptr [ebp-0Ch],ecx ;[ebp-0Ch] = ecx0040D7AC cmp dword ptr [ebp-0Ch],3 ;比较[ebp-0ch]和3大小0040D7B0 ja $L40+18h (0040d7ec) ;ecx大于3则跳到default0040D7B2 mov edx,dword ptr [ebp-0Ch] ;0040D7B5 jmp dword ptr [edx*4+40D845h];40D845h应该是指针存放的位置,这里就是跳到相应的case执行case 1:
这里比较特殊,因为case都是相差1的,编译器做了优化,这样效率高一些。上面是检查a是否超出最大的case 4,超出就跳到default执行,否则就跳到相应的case。
2)
main()
{ int a = 0; int o = 0; a = 4; switch(a) { case 1: o = 10; printf("%d\n",o); case 20: o = 20; printf("%d\n",o); default: o = 100; printf("%d\n",o); case 300: o = 30; printf("%d\n",o); case 40: o = 40; printf("%d\n",o); }}
反汇编代码:
switch(a)
{ 0040D79D mov eax,dword ptr [ebp-4]0040D7A0 mov dword ptr [ebp-0Ch],eax0040D7A3 cmp dword ptr [ebp-0Ch],28h0040D7A7 jg main+4Dh (0040d7bd)0040D7A9 cmp dword ptr [ebp-0Ch],28h0040D7AD je main+0B8h (0040d828)0040D7AF cmp dword ptr [ebp-0Ch],10040D7B3 je main+58h (0040d7c8)0040D7B5 cmp dword ptr [ebp-0Ch],14h0040D7B9 je main+70h (0040d7e0)0040D7BB jmp main+88h (0040d7f8)0040D7BD cmp dword ptr [ebp-0Ch],12Ch0040D7C4 je main+0A0h (0040d810)0040D7C6 jmp main+88h (0040d7f8) ;这里是跳到default去case 1:这里是将各case改得复杂一点,没有规律了,然后程序就必须一个一个的验证case是否满足,都满足的话最后就直接jmp跳到default去执行。
总结:所以在程序中default的位置可以任意,因为编译到exe后,程序执行时先判断所有case,然后再判断是否跳到default的地址(即指针),然后往后执行,遇到break之类的就直接跳到后面去了。(而各case和default的内嵌语句又是顺序的)