前几天有一个同事询问,switch和case语句中间的代码是否会执行?
本能的认为,不会被执行!!
又想了一下原理,从汇编的角度,无论是switch还是if,最后的汇编代码都是一条条判断语句。
只是在C语言语法上有不同的写法而已,所以我要证明一下我的想法。
一、首先,写一段测试代码:
#include <string.h>
#include <stdio.h>
int main(int argc,char* argv[])
{
unsigned int uiSwitch;
for(uiSwitch = 0;uiSwitch < 5;uiSwitch++)
{
switch(uiSwitch)
{
/* 下面这行Log是否会输出呢? */
printf("This is no output log \r\n");
case 0:
printf("This is %d \r\n",uiSwitch);
break;
case 1:
printf("This is %d \r\n",uiSwitch);
break;
case 2:
printf("This is %d \r\n",uiSwitch);
break;
case 3:
printf("This is %d \r\n",uiSwitch);
break;
default:
printf("This is default %d \r\n",uiSwitch);
break;
}
}
return 0;
}
当然,最后执行结果,没有那行Log的输出,如下:
This is 0
This is 1
This is 2
This is 3
This is default 4
二、让我们看看汇编代码:
因为switch语句只有4个case,所以有4个cmp判断语句,用来比较后跳转到对应的case代码中。
当所有cmp的判断都没有成立的情况下,执行default处理中的jmp指令。
所以,switch和case中间的语句不会执行,并且都不生成汇编代码,属于代码Miss。
400541: 8b 45 fc mov -0x4(%rbp),%eax
400544: 83 f8 01 cmp $0x1,%eax
400547: 74 27 je 400570 <main+0x4a>
400549: 83 f8 01 cmp $0x1,%eax
40054c: 72 0c jb 40055a <main+0x34>
40054e: 83 f8 02 cmp $0x2,%eax
400551: 74 33 je 400586 <main+0x60>
400553: 83 f8 03 cmp $0x3,%eax
400556: 74 44 je 40059c <main+0x76>
400558: eb 58 jmp 4005b2 <main+0x8c>
[main函数全部汇编]
0000000000400526 <main>:
#include <string.h>
#include <stdio.h>
int main(int argc,char* argv[])
{
400526: 55 push %rbp
400527: 48 89 e5 mov %rsp,%rbp
40052a: 48 83 ec 20 sub $0x20,%rsp
40052e: 89 7d ec mov %edi,-0x14(%rbp)
400531: 48 89 75 e0 mov %rsi,-0x20(%rbp)
unsigned int uiSwitch;
for(uiSwitch = 0;uiSwitch < 5;uiSwitch++)
400535: c7 45 fc 00 00 00 00 movl $0x0,-0x4(%rbp)
40053c: e9 8a 00 00 00 jmpq 4005cb <main+0xa5>
{
switch(uiSwitch)
400541: 8b 45 fc mov -0x4(%rbp),%eax
400544: 83 f8 01 cmp $0x1,%eax
400547: 74 27 je 400570 <main+0x4a>
400549: 83 f8 01 cmp $0x1,%eax
40054c: 72 0c jb 40055a <main+0x34>
40054e: 83 f8 02 cmp $0x2,%eax
400551: 74 33 je 400586 <main+0x60>
400553: 83 f8 03 cmp $0x3,%eax
400556: 74 44 je 40059c <main+0x76>
400558: eb 58 jmp 4005b2 <main+0x8c>
{
/* 下面这行Log是否会输出呢? */
printf("This is no output log \r\n");
case 0:
printf("This is %d \r\n",uiSwitch);
40055a: 8b 45 fc mov -0x4(%rbp),%eax
40055d: 89 c6 mov %eax,%esi
40055f: bf 64 06 40 00 mov $0x400664,%edi
400564: b8 00 00 00 00 mov $0x0,%eax
400569: e8 92 fe ff ff callq 400400 <printf@plt>
break;
40056e: eb 57 jmp 4005c7 <main+0xa1>
case 1:
printf("This is %d \r\n",uiSwitch);
400570: 8b 45 fc mov -0x4(%rbp),%eax
400573: 89 c6 mov %eax,%esi
400575: bf 64 06 40 00 mov $0x400664,%edi
40057a: b8 00 00 00 00 mov $0x0,%eax
40057f: e8 7c fe ff ff callq 400400 <printf@plt>
break;
400584: eb 41 jmp 4005c7 <main+0xa1>
case 2:
printf("This is %d \r\n",uiSwitch);
400586: 8b 45 fc mov -0x4(%rbp),%eax
400589: 89 c6 mov %eax,%esi
40058b: bf 64 06 40 00 mov $0x400664,%edi
400590: b8 00 00 00 00 mov $0x0,%eax
400595: e8 66 fe ff ff callq 400400 <printf@plt>
break;
40059a: eb 2b jmp 4005c7 <main+0xa1>
case 3:
printf("This is %d \r\n",uiSwitch);
40059c: 8b 45 fc mov -0x4(%rbp),%eax
40059f: 89 c6 mov %eax,%esi
4005a1: bf 64 06 40 00 mov $0x400664,%edi
4005a6: b8 00 00 00 00 mov $0x0,%eax
4005ab: e8 50 fe ff ff callq 400400 <printf@plt>
break;
4005b0: eb 15 jmp 4005c7 <main+0xa1>
default:
printf("This is default %d \r\n",uiSwitch);
4005b2: 8b 45 fc mov -0x4(%rbp),%eax
4005b5: 89 c6 mov %eax,%esi
4005b7: bf 72 06 40 00 mov $0x400672,%edi
4005bc: b8 00 00 00 00 mov $0x0,%eax
4005c1: e8 3a fe ff ff callq 400400 <printf@plt>
break;
4005c6: 90 nop
int main(int argc,char* argv[])
{
unsigned int uiSwitch;
for(uiSwitch = 0;uiSwitch < 5;uiSwitch++)
4005c7: 83 45 fc 01 addl $0x1,-0x4(%rbp)
4005cb: 83 7d fc 04 cmpl $0x4,-0x4(%rbp)
4005cf: 0f 86 6c ff ff ff jbe 400541 <main+0x1b>
printf("This is default %d \r\n",uiSwitch);
break;
}
}
return 0;
4005d5: b8 00 00 00 00 mov $0x0,%eax
4005da: c9 leaveq
4005db: c3 retq
4005dc: 0f 1f 40 00 nopl 0x0(%rax)
以上,没啦