switch语句分析

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语句代码:连续的分支常量,但中间缺少了一定数量的常量;
 
反汇编:
内存:
 
 
 

猜你喜欢

转载自www.cnblogs.com/ShiningArmor/p/11578572.html