1.关于switch语句
如果if语句中表达式是判断是否等于一个常量时,可以用switch语句来代替
if(表达式 == 常量1)
{
//...代码
}
else if(表达式 == 常量2)
{
//...代码
}
else if(表达式 == 常量3)
{
//...代码
}
else
{
//...代码
}
相当于:
switch(表达式)
{
case 常量表达式1:
语句;
break;
case 常量表达式2:
语句;
break;
case 常量表达式3:
语句;
break;
case 常量表达式4:
语句;
break;
default:
语句;
break;
}
也就是说:
switch语句 是if语句的简写
switch要求:
1、case后面必须是常量表达式
2、case后常量表达式的值不能一样
3、switch后面表达式必须为整数
如果不要break,将在满足条件的表达式处开始一直向下执行,直到见到break为止;
当条件都不满足时执行default后的语句;
2.反汇编分析
1)当分支较少时switch和if差别多,都是每个分支都判断,然后执行相关语句;
void fun()
{
int i = 2;
switch(i){
case 1:
printf("1");
break;
case 2:
printf("2");
break;
case 3:
printf("3");
break;
default:
printf("4");
break;
}
}
int main(int argc, char* argv[])
{
fun();
getchar();
return 0;
}
2)当有多个分支时switch的性能优于if
不需要每个分支都判断;
void fun()
{
int i = 2;
switch(i){
case 1:
printf("1");
break;
case 2:
printf("2");
break;
case 3:
printf("3");
break;
case 4:
printf("4");
break;
case 5:
printf("5");
break;
case 6:
printf("6");
break;
default:
printf("7");
break;
}
}
int main(int argc, char* argv[])
{
fun();
getchar();
return 0;
}
反汇编分析:
跳转到case2处:
结果:
switch语句的强悍之处在于,它会在哪内存中生成一张表,存储每一条分支语句的地址;
当把分支条件传进来时,可以通过表达式直接定位到真正要跳转到的分支语句地址;
如果把case的常量交换顺序,依然可以正确定位到对应的分支;
3)规律
1】分支少于一定数量时,用switch没有意义;
因为编译器此时不会为switch不生成大表,和if一样需要每个参数都判断;
2】case后面的常量可以是无序的,并不影响大表的生成;
3】为了生成大表,通常会减去最小值的case常量,以此来确定大表的地址;
例如:如果最小的分支常量为1,则有sub ecx,1;如果最小分支常量是301,则sub ecx,301;以此类推;
4】如果常量连续,但中间缺少少数几个常量,大表会在缺少的地方放default的地址;
5】如果常量连续,但中间缺少的常量达到一定数量,编译器为了节省内存,会采取创建小表的策略;
小表占一个字节的空间;因此如果间隔超过255个数将无法生成小表;
6】如果分支常量毫无规律差值过大、编译器为了节省内存将不会生成大表和小表;
4)编译器创建小表时的反汇编
switch语句代码:连续的分支常量,但中间缺少了一定数量的常量;
反汇编:
内存: