VS_C_17/11/22 C中if与switch的区别
来源:互联网 发布:群星修改数据 编辑:程序博客网 时间:2024/06/06 08:28
一:两种语句的区别
在讨论if与switch这两种语句的区别时,应该从它们最基础的层面开始。所以我们应该从它们的汇编实现开始探讨。而且应注意到它们都是C中最常用的选择语句,既然是选择语句就还得从它们的实现效率上讨论一番。
先看switch语句:
1,switch...case会生成一个跳转表来指示实际的case分支的地址,而这个跳转表的索引号与switch变量的值是相的。从而,switch...case,只需访问对应索引号的表项从而到达定位分支的目的。
switch...case会生成一份大小(表项数)为最大case常量+1的查询表,程序首先判断switch变量是否大于最大case常量,若大于,则跳到default分支处理;否则取得索引号为switch变量大小的查询表项的地址(即查询表的起始地址+表项大小*索引号),程序接着跳到此地址执行。
我们可以用VS来看一下:
switch-case在实现时当case项比较多时,会通过生成查询表来提高程序的效率,空间换时间。
而这个界限一般是4(所以我们用了4个选择)即大于4个选项时,switch就会生成一个查询表,并且在执行switch以下语句(case)时已经查询了一次,在执行case查找常量时只需要对应表格个常量位置执行其对应的语句既可。
我们来看一下这段代码的汇编语言:
这段汇编语言中,可以看到上面红色标出的,在switch的汇编语言中,在达到4个的选择时,只会进行一次查询,而且是在case指令之前就已执行,这也应证了前面对查询表的解释。switch (i)
00F913E5 mov eax,dword ptr [i]
00F913E8 mov dword ptr [ebp-0D0h],eax
00F913EE cmp dword ptr [ebp-0D0h],4 //cmp 在汇编中一条查询指令
00F913F5 ja $LN6+2Dh (0F91431h) //ja指令用于无符号数比较,取jump if above,及前者大于后者则转移
00F913F7 mov ecx,dword ptr [ebp-0D0h]
00F913FD jmp dword ptr [ecx*4+0F91468h] //即查询表的起始地址+(输入值 - 1)* 索引号
case 0: 中括号在汇编中类似于C中的指针,即取地址的意思。这句执行后就将中括号中算出的
j = 0; 地址中存的操作数取出,这个操作数就是case下的地址00F9141F(可验证)
00F91404 mov dword ptr [j],0
break;
00F9140B jmp $LN6+34h (0F91438h) // jmp在汇编中为无条件跳转
case 1:
j = 1;
00F9140D mov dword ptr [j],1
break;
00F91414 jmp $LN6+34h (0F91438h)
case 2:
j = 2;
00F91416 mov dword ptr [j],2
break;
00F9141D jmp $LN6+34h (0F91438h)
case 3:
j = 3;
00F9141F mov dword ptr [j],3
break;
00F91426 jmp $LN6+34h (0F91438h)
case 4:
j = 4;
00F91428 mov dword ptr [j],4
break;
00F9142F jmp $LN6+34h (0F91438h)
default:
j = 10;
00F91431 mov dword ptr [j],0Ah
break;
}
printf("%d\n", j);
0F91438h mov esi,esp
JMP 在汇编中表示无条件跳转,可以看到它出现了6次,代表代码中有6次跳转。
可以看到在每个case之后都有一个蓝色标注的地址,这其实就是前面JMP跳转到的地址,这个地址其实就是printf之后的一个地址,意思是在switch之后如果 i 与case之后的立即数相同就跳转到printf打印。
2,下来我们来看if语句:
我同样对if语句做了4个及以上的选择。而且我们用5来实验它的查询效率。
要知道if语句的实现基础还是需要汇编代码,,其采用遍历查询的方式。我们根据上面的思路只需要知道if语句的代码中cmp(查询)的个数:
一: if (j == 0)
010113EE cmp dword ptr [j],0
010113F2 jne lbf1+3Fh (01011429h) //jne 有条件跳转
二: if (j == 1)
01011429 cmp dword ptr [j],1
三: if (j == 2)
01011430 cmp dword ptr [j],2
01011434 jne lbf1+81h (01011451h)
四: if (j == 3)
01011451 cmp dword ptr [j],3
01011455 jne lbf1+0A2h (01011472h)
五: if (j == 4)
01011472 cmp dword ptr [j],4
01011476 jne lbf1+0C3h (01011493h)
六: if (j == 5)
01011493 cmp dword ptr [j],5
01011497 jne lbf1+0E4h (010114B4h)
可以看出在条件为5时需要查询6次即每个条件都查询了一次,效率显然没有switch高,在语句中需要遍历条件分支直到命中条件,这也说明在写if语句的时候需要把可能性大的条件放在前面。
在if的汇编中也有类似于上面switch中的JMP跳转,但这里是jne(有条件跳转)。意思是在if进行判断时,如果为真就执行if内部语句块,如果为假则有条件跳转到下一个if语句,直到判断为真执行语句块。
二:两种语句的共性
两者虽有差距,但它们的基本原理相似,都是与C中的立即数相比较,相等时打印并跳转返回。而且经过比较,switch语句在选择数小于4时也会执行超过一个cmp指令。
就有点类似于if语句了。
三:总结语句的特点
1,当分支较多时,使用switch语句的效率比if语句高很多。
2,switch语句其实是一种空间换时间的方法,在case常量分布范围很大但实际有效值又比较少的情况switch的效果并不是很好。而且if语句有较大的灵活性,switch只能查询常量。
3,switch只能处理case为常量的情况,其灵活性相比于if语句差很多。
4,在使用if语句时将可能性最大的条件放在前面可提高if语句的效率。
- VS_C_17/11/22 C中if与switch的区别
- VS_C_17/12/12 C中数组与宏和const的总结
- if与switch的使用与区别
- if与switch区别
- switch与if的区别(1)
- switch()与if()语句的区别新发现
- if else 与 switch case的区别:
- if else 与switch的区别 -switch用法
- switch与if..else区别
- php if与switch区别
- if else与switch区别
- C语言中switch case语句的实现(switch case 和 else if 的比较、区别)
- if和switch的区别
- If 跟 switch 的区别
- if和switch的区别
- JavaScript中if和switch的区别和运用
- switch与if的效率
- VS_C_17/12/17 C的数组的扩充与指针的引入
- 问题 G: C语言实验题——某年某月的天数(JSU-ZJJ)
- 网站设计| 网站设计模板素材
- 记录以下Java的基本知识
- 图的幂律度分布 power-law degree distributios
- 记第一次用C语言写代码的经历
- VS_C_17/11/22 C中if与switch的区别
- 嵌套类和内部类(转,有修改)
- 安卓软件安装成功后通过广播-接收器删除apk文件
- 问题 H: 逆置正整数
- python selenium开关网页刷新流量
- 计算机科学与Python编程导论_MIT 学习笔记(一)
- 问题 I: 找中间数
- 问题 J: C语言实验题——温度转换(JSU-ZJJ)
- Excel在统计分析中的应用—第九章—非参数检验-x2检验-正态分布拟合优度检验