编译器是否有权甚至能够优化算术运算,其中一方是整数类型,而另一方是浮点数?或者,在100%的情况下执行操作之前,整数是否会被提升为浮点数?
我问的原因是因为我喜欢为了清晰起见而自己执行浮动促销,但如果它保留了编译器可以利用的情况,我可能会停止这样做。
答案 0 :(得分:7)
如果编译器可以优化float
和整数之间的加法,例如优化3.f + 1
到4
而不是在运行时执行加法,我会期望转换的存在对编译器是否可以优化没有影响。
这是一个基于现代编译器工作方式而非逻辑必然性的一般性陈述。在编译器认识到可以优化某些f + i
的情况下,某些float
f
和某些整数i
(可能是常量或表达式,而不仅仅是标识符),然后{ {1}}在编译器的分析中应该是等效的,并且应该接收相同的优化。
理解其原因的一种方法是,在解析f + (float) i
时,编译器将识别出f + i
必须转换为i
,并且它将在其内部表示中构造程序,获取float
的语句,获取f
,将i
转换为i
,然后添加它们。在分析float
时,将构造相同的内部表示,因此这两个语句将是等效的。
那就是说,我希望编译器可以优化的情况可能相当有限。编译器可以识别特定情况,例如添加两个常量,将f + (float) i
零添加到整数,以及将整数0添加到float
。有时编译器可能能够推导出float
和f
的值,即使它们是表达式或标识符,而不是常量,因为先前代码的流量必然产生一些值,然后它可能能够根据推导出的值进行优化。
因此,可以识别特殊情况。我不希望编译器通常能够将i
转换为任何类型的优化比特,它比浮点数(或编译器通常使用的任何指令)更快。但是,从理论上讲,它可能会发生,如果是这样,设计良好的编译器应该优化f + i
与f + i
相同。 (也许有一些C实现在软件中支持浮点支持而不是硬件,它可以以比添加两个浮点值的更快的方式处理浮点值和整数的添加。)
答案 1 :(得分:2)
我很好奇,所以我做了一些快速测试,并且我观察到了以下行为:
这段代码的执行时间是:
for (int i = 0; i < 1000000000; ++i) {
f = f + 1;
}
通过浮动促销:
for (int i = 0; i < 1000000000; ++i) {
f = f + (float)1;
}
这只是一种情况。当然,这不是检查的最佳方式,我确信编译器可以根据情况做得更好或更差,但我观察到与O2优化的时间有点不同。
**在c ++ 11中运行。 CPU架构:AMD64 **