某日一个同学在做算法题,(旅游背包)在OJ系统提交时超时 我们在设法优化代码减少运行时间时,发现貌似If-else比三目运算?: 更快一点。 于是,用VC写了一段简短的测试。同样是双重循环中执行 if-else与三目运算,计算其花费的时间。

a=100,b=50,n为测试变量
start=clock();
for(i=1;i<=n;i++)
{for(j=1;j<=n;j++){if(a>b)temp=a;elsetemp=b;}
}
end=clock();
cout << "Time= "<<end-start<<endl;for(i=1;i<=n;i++)
{for(j=1;j<=n;j++){temp=a>b?a:b;}
}
以下是测试结果: 
time单位为 msn=100If time = 0The :? time = 0n=1000If time = 2The :? time = 4n=10,000  If time = 253The :? time = 360n=50,000  If time = 6209The :? time = 8941n=100,000   If time = 24343The :? time = 35807

    可以见到,随着n越大,两者差距越来越明显(未经多台电脑测试,仅经自己台试,神奇的是在Ubuntu下没多大差别,这问题在后面说),然后我通过反编译,查看它们的汇编代码,发现一件令我不解的神奇事。
  
以下分别是If-else与三目运算的汇编代码。
37:               if(a>b)
00401079   mov         ecx,dword ptr [ebp-10h]
0040107C   cmp         ecx,dword ptr [ebp-14h]
0040107F   jle         main+79h (00401089)
38:                   temp=a;
00401081   mov         edx,dword ptr [ebp-10h]
00401084   mov         dword ptr [ebp-18h],edx
39:               else
00401087   jmp         main+7Fh (0040108f)
40:                   temp=b;
00401089   mov         eax,dword ptr [ebp-14h]
0040108C   mov         dword ptr [ebp-18h],eax51:               temp=a>b?a:b;
004010F3   mov         edx,dword ptr [ebp-10h]
004010F6   cmp         edx,dword ptr [ebp-14h]
004010F9   jle         main+0F3h (00401103)
004010FB   mov         eax,dword ptr [ebp-10h]
004010FE   mov         dword ptr [ebp-24h],eax
00401101   jmp         main+0F9h (00401109)
00401103   mov         ecx,dword ptr [ebp-14h]
00401106   mov         dword ptr [ebp-24h],ecx
00401109   mov         edx,dword ptr [ebp-24h]
0040110C   mov         dword ptr [ebp-18h],edx

    可见后者比前者多了两条指令。
    If-else无论在何种情况下(在if中或者else中),都是通过先将需要赋的变量值传给寄存器然后再通过寄存器赋值给temp变量 。即
    mov edx,b; mov temp,edx ;
    然而,对于三目运算,它其中一步却增加多了一个临时变量。  
    mov ecx,b;mov NEWTEMP,ecx;
    mov edx,NEWTEMP;mov temp;edx;
    
    以下是一个同学给我的答案(他从编译原理课上学的):
    因为三目运算是先运算,再赋值!
    例如 :  
       temp = a > b ? a : b ;
       a > b ? a : b 是运算,  temp = (a > b ? a : b )是赋值。
       所以在三目的汇编里面  a,b,temp地址 为10h,14h 18h  无论a>b的结果怎样,都有先将它后              面的结果保存在地址为  24h 的中间变量里面 ,然后再 赋值给地址为 18h 的temp变量中!
               
     而 if 语句是直接赋值 ,不存在运算,所以快了一点。
然后根据这原理,可以知道 ++i 比 i++ 快, x+=y 比 x=x+y 快。
不过,我们写程序的时候可以忽略它们,因为这种东西,编译器已经帮我们优化了!!!
所以不管你写 i++ 还是 ++i ,它都是一样的 ,以下是证明。
00401048   mov         dword ptr [ebp-4],1
32:
33:       ++i;
0040104F   mov         eax,dword ptr [ebp-4]
00401052   add         eax,1
00401055   mov         dword ptr [ebp-4],eax
34:
35:       i++;
00401058   mov         ecx,dword ptr [ebp-4]
0040105B   add         ecx,1
0040105E   mov         dword ptr [ebp-4],ecx

    可是为什么VC没有优化这个三目运算?把它改成if形式?
    回到上面遗留的问题,为何Ubuntu下运行没区别?----> 或许Ubuntu下的编译器把它优化了
    之前在百度找了一下答案,说是如果将三目赋的值变为常量,这样的话执行起来无需要像if-else那样跳转,利于CPU执行。(这涉及到硬件,我不懂,也没兴趣继续刨根问底了~这问题,到此结束吧。)
以下是常量的汇编代码。 确实没有跳转指令  将1:0换成其他数字,经测试也是没有,虽然指令会多了几条。
38:       z=x>y?1:0;
0040106E   mov         ecx,dword ptr [ebp-8]
00401071   xor         edx,edx
00401073   cmp         ecx,dword ptr [ebp-0Ch]
00401076   setg        dl
00401079   mov         dword ptr [ebp-4],edx

If-else与三目运算符的区别相关推荐

  1. Java if语句深度解析

    用于一种情况下的判断 格式:if(判断表达式){ 条件表达式为true的时候执行的内容 } 小案例: package hello; public class day1 { public static ...

  2. C++基础知识点小结

    C++基础知识点小结 第一章 绪论 (1)cout 输出流的对象 (2)cin输入对象 (3)endl 输出控制符/操控符 (4)标识符 (5)命名空间(namespace) (6)左值: (7)右值 ...

  3. 0基础Java学习——第一周

    目录 Day1 一.存储单位: 二.常用的DOS命令: 三.Java三平台: 四.Java注释: 五.运行Java程序所具备的条件 Day2 一.标识符 二.关键字,保留字 三.Java基本数据类型: ...

  4. 数字IC笔试面试常考问题及答案

    来源:知乎 链接:https://zhuanlan.zhihu.com/p/261298869 基础知识 原理务必理解透彻. 锁存器的结构-DFF的结构-建立保持时间-亚稳态-STA-CDC. 亚稳态 ...

  5. swift 学习(一)

    swift学习 一.基础部分 1. 常量(let) 变量(var) swift能够自己推断变量的类型,可以不用写变量的类型 let test = "你好,世界!!" let tes ...

  6. JS中三目运算符和if else的区别

    今天写了一个图片轮播的小demo,用到了判断 先试了一下if else,代码如下: if(n >= count-1){ n =0; }else{ n ++; } 随后代码写完了,准备优化一下代码 ...

  7. js三目运算符判断_JS中三目运算符和if else的区别分析与示例

    今天写了一个图片轮播的小demo,用到了判断 先试了一下if else,代码如下: if(n >= count-1){ n =0; }else{ n ++; } 随后代码写完了,准备优化一下代码 ...

  8. js 中的单目运算符,双目运算符与三目运算符区别

    单目运算符 :运算符只对一个变量进行操作. 双目运算符 :对两个变量进行操作. 三目运算符:运算符对三个变量进行操作. 这里记录一下.

  9. shell [] [[ ]] {}区别

    一.小括号,圆括号() 1.单小括号 () ①命令组.括号中的命令将会新开一个子shell顺序执行,所以括号中的变量不能够被脚本余下的部分使用.括号中多个命令之间用分号隔开,最后一个命令可以没有分号, ...

最新文章

  1. 《科学》十大年度科学突破反映的新动向
  2. async 队列性能测试
  3. python raise 引起的异常
  4. 对javascript中的匿名函数的理解
  5. 爬虫新宠requests_html 带你甄别2019虚假大学 #华为云·寻找黑马程序员#
  6. “去QE”时代下,QE如何破茧重生?
  7. java实现英文文件单词搜索系统_java对于目录下文件的单词查找操作代码实现
  8. [转载] Python:numpy中array的用处
  9. pe_xscan做了几个改动
  10. 对WordCOM类工厂80070005和8000401a错误分析及解决办法(DCOM)的补充
  11. 如何创建自己的本地高级URL缩短服务
  12. 未来教育软件计算机二级不能评分怎么办,为什么计算机二级软件打不开
  13. 无线网卡服务器关闭了怎么办,台式机无线网卡自动禁用怎么办
  14. Cartesian coordinate system
  15. Python识别二维码获取电子发票基本信息
  16. VS2008单元测试之调用的目标发生了异常
  17. 计算机物理学论文300字,物理考试反思范文300字(精选6篇)
  18. H. 知识图谱 知识问答
  19. 银行付款出现java,SSH框架网上商城项目第22战之银行图标以及支付页面显示
  20. 百度DuerOS+ARM 加出了赋能合作伙伴的哪些能力?

热门文章

  1. MiniGUI——第一个程序helloworld
  2. 这些程序员常用快捷键你了解吗?让你的双手在键盘上起舞
  3. 强烈推荐的程序员键盘--红轴手感好按键压力小写代码更轻松
  4. “王峰十问”走进2019数博会,与凯文·凯利等人激辩区块链
  5. mysql出现core dumped_mysql 段错误 (core dumped)
  6. python获取声音波形的关键特征
  7. Unirech腾讯云代充-云服务器登陆及远程连接常见问题
  8. cad角度怎么画_软件CAD | 各种“线”工具
  9. oracle下的inventory文件夹,Oracle软件安装目录信息Inventory作用以及如何重建此目录 - 2...
  10. Linux的iio数据流程,Linux 工业输入输出IIO子系统框架.doc