pol*_*ఠ_ఠ 3 c c++ compilation compiler-optimization
这是一个普遍的问题,但由于我主要处理gcc/g ++/VStudio,我将其标记为c/c ++.当我搞乱优化选项时,我想到了这个问题.在最简单的形式中,考虑算术运算,如i / 6 * 8.如果一个人面对这个表达,他很可能将它简化为类似的东西i / 3 * 4.如果他更习惯乘以4,他将首先这样做,即(i * 4) / 3.我必须再次强调,这只是一个简单的例子.
那么编译器呢?他们是否有可能对此类操作采取相同措施?而且既然我们知道在上面的例子中,如果i是一个整数,那么简化和改变操作的顺序可能会导致完全不同的结果,问题可以改为:编译器是否完全避免了这样的动作?
如果我们希望程序完全按照我们的说法进行一些算术运算而不改变运算顺序,那么我们是否应该担心编译器的行为?
最有可能的是,编译器会将"常量折叠"和"常量传播"优化应用于常量表达式.
在上面的例子中,编译器不能应用这样的优化.
想像
i = i * (4/2)
Run Code Online (Sandbox Code Playgroud)
编译器会生成
i= i * 2
Run Code Online (Sandbox Code Playgroud)
这是因为不断折叠.
编译器在优化代码时非常保守.它们可能会改变执行操作的顺序,甚至可以预先计算操作数在编译时已知的算术运算(这称为常量折叠),但它们永远不会改变计算结果.浮点运算有点问题.在不更改计算结果的情况下,通常无法更改计算顺序或预先计算.因此,大多数编译器默认情况下保留原样.然而,有可能要求编译器积极优化; 在这种情况下,计算结果可能会改变,但用户要求它.例如,这是gcc选项的情况-Ofast(因为它在内部设置选项-ffast-math).请注意,它可能会导致奇怪的副作用,例如零意外的"随机"划分.
**编辑:关于非算术运算的注释**
当代码包含指针和函数调用时,优化变得更加困难.一般来说,预测副作用是不可能的(考虑指针别名和全局变量).因此编译器总是以非常保守的方式放弃:一个好的编译程序至少应该是正确的,快速是一种奢侈.
**编辑:一些例子**
这个SO问题给出了浮点可能发生的非常详细的示例:启用优化的不同浮点结果 - 编译器错误?