独闷闷网

 找回密码
 立即注册
搜索
查看: 1096|回复: 0
收起左侧

[原创] switch语句等价于if和else if语句吗?用switch在主循环时应注意什么问题?已解答。

[复制链接]
发表于 2016-9-25 14:07:50 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
★坚鸿-深圳:


  1. void main()
  2.   {
  3.    //此处暂时省略了一些代码
  4.    while(1)  
  5.    {
  6.        key_service(); //按键服务的应用程序
  7.    }

  8. }

  9. void key_service() //按键服务的应用程序
  10. {

  11.   switch(ucKeySec) //按键服务状态切换
  12.   {
  13.     case 1:// 1号键
  14.           //在这里添加应用代码
  15.           ucKeySec=0;  //响应按键服务处理程序后,按键编号清零,避免一致触发
  16.           break;        
  17.     case 2:// 2号键
  18.           //在这里添加应用代码
  19.           ucKeySec=0;  //响应按键服务处理程序后,按键编号清零,避免一致触发
  20.           break;   
  21.     case 3:// 3号键
  22.           //在这里添加应用代码
  23.           ucKeySec=0;  //响应按键服务处理程序后,按键编号清零,避免一致触发
  24.           break;   
  25.     case 4:// 4号键
  26.           //在这里添加应用代码
  27.           ucKeySec=0;  //响应按键服务处理程序后,按键编号清零,避免一致触发
  28.           break;  
  29.                
  30.   }     
  31.            
  32. }
复制代码

上述代码是常见的按键服务函数里面的switch框架,大家看看,能发现什么问题吗?看看,咋看,风平浪静,啥事都没有。我现在,我把它等效转换成if和else if语句,如下:

  1. void main()
  2.   {
  3.    //此处暂时省略了一些代码
  4.    while(1)  
  5.    {
  6.        key_service(); //按键服务的应用程序
  7.    }

  8. }

  9. void key_service() //按键服务的应用程序
  10. {

  11.    if(1==ucKeySec)
  12.    {
  13.       //在这里添加应用代码
  14.       ucKeySec=0;  //响应按键服务处理程序后,按键编号清零,避免一致触发
  15.    }
  16.    else if(2==ucKeySec)
  17.    {
  18.       //在这里添加应用代码
  19.       ucKeySec=0;  //响应按键服务处理程序后,按键编号清零,避免一致触发
  20.    }
  21.    else if(3==ucKeySec)
  22.    {
  23.       ucKeySec=0;  //响应按键服务处理程序后,按键编号清零,避免一致触发
  24.    }
  25.    else if(4==ucKeySec)
  26.    {
  27.       ucKeySec=0;  //响应按键服务处理程序后,按键编号清零,避免一致触发
  28.    }
  29.            
  30. }
复制代码


大家假设想想一下,假如你的按键里有48个按键,往里面添加48个else if,当没有按键触发的时候,每次从主循环进入这个函数,都要判断“if和else if"大概48次!如果添加一行代码,让平时没有按键时候只进来判断一次该多好。这个是大家很容易忽略的问题,现在分析给大家,那么这行代码就是在这个函数最上面添加:

  1. if(0==ucKeySec)
  2. {
  3.     return; //直接退出这个函数,后面不需要再多判断它无用的48回
  4. }
复制代码


完整的代码如下:

  1. void main()
  2.   {
  3.    //此处暂时省略了一些代码
  4.    while(1)  
  5.    {
  6.        key_service(); //按键服务的应用程序
  7.    }

  8. }
  9. void key_service() //按键服务的应用程序
  10. {

  11.   if(0==ucKeySec)  //只有老练的工程师才会懂得欣赏这句精妙的语句!
  12.   {
  13.      return; //直接退出这个函数,后面不需要再耗时间去轮番逐个判断case
  14.   }

  15.   switch(ucKeySec) //按键服务状态切换
  16.   {
  17.     case 1:// 1号键
  18.           //在这里添加应用代码
  19.           ucKeySec=0;  //响应按键服务处理程序后,按键编号清零,避免一致触发
  20.           break;        
  21.     case 2:// 2号键
  22.           ucKeySec=0;  //响应按键服务处理程序后,按键编号清零,避免一致触发
  23.           break;   
  24.     case 3:// 3号键
  25.           ucKeySec=0;  //响应按键服务处理程序后,按键编号清零,避免一致触发
  26.           break;   
  27.     case 4:// 4号键
  28.           ucKeySec=0;  //响应按键服务处理程序后,按键编号清零,避免一致触发
  29.           break;         
  30.   }     
  31.            
  32. }
复制代码

精华.jpg

★啦啦-青岛:
switch是只判断一次,IF是逐条判断的吧,两者不一样。

★坚鸿-深圳:
switch语句转换成汇编,它本质是用什么语句实现,这个是问题的关键点。我刚好在网上查看了一下资料。发现不同的C编译器对switch语句的处理是不一样的,主要有两种思路:

第一种:就是等效成if和else if语句那样的汇编代码来处理,这是逐行判断。比如,像下面的就是逐行判断的汇编代码:
C原.png
上述C语言翻译成汇编如下:
汇编.png

这里的cmp和je的汇编组合语句就相当于C语言的if语句。


第二种:就是用到汇编查表跳转的指令,这种思路不用逐行判断。

综上所述,结论是:不同的C编辑器对switch处理是不一样的,有的是用汇编的查表原理不用逐行判断,有的是用if逐行判断,对于我们,最好做最坏的打算来预防最坏的情况,所以我今天推荐给大家的那一行代码程序,是有必要加上的。

Alex-昆山:
我以前用汇编写过switch语句,就是用查表功能的,如下:
查表跳转.jpg

乐于分享,勇于质疑!
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|独闷闷网 ( 粤ICP备12007667号-2 )

GMT+8, 2018-6-24 07:23 , Processed in 0.113765 second(s), 21 queries .

快速回复 返回顶部 返回列表