c – 是否存在算术运算受编译器优化影响的情况?

这是一个普遍的问题,但由于我主要处理 gcc / g / VStudio,我将其标记为c / c.当我搞乱优化选项时,我想到了这个问题.在最简单的形式中,考虑一个算术运算,如i / 6 * 8.如果一个人面对这个表达式,他很可能将它简化为像i / 3 * 4这样的东西.如果他更习惯乘以4,他将首先这样做,即(i * 4)/ 3.我必须再次强调,这只是一个简单的例子.

那么编译器呢?他们是否有可能对此类操作采取相同措施?而且由于我们知道在上面的例子中,如果我是一个整数,那么简化和改变操作的顺序可能会导致完全不同的结果,问题可以改为:编译器完全避免这样的行为吗?

如果我们希望程序完全按照我们的说法进行一些算术运算而不改变运算顺序,那么我们是否应该担心编译器的行为?

解决方法

正如其他答案所解释的那样,有效的编译器必须保守,不得采用任何可能改变定义良好的程序行为的优化.但重要的是要记住,这种保守主义仅适用于有效的,写得恰当,定义明确的程序.如果编译的代码依赖于未定义的行为,那么现代编译器在它们使用的优化中可能是完全激进的,而在现实世界中,这意味着所述问题的答案实际上是,“是的,有些情况下算术编译器优化会影响操作.“

这里有两个很棒的网页,描述了编译器在遇到未定义的行为时有时会应用的一些改变意义的优化:

>“What Every C Programmer Should Know About Undefined Behavior
>“A Guide to Undefined Behavior in C and C++

编程语言定义通常被描述为程序员和程序之间作为一方的“契约”,编译器及其实现者作为另一方.只要您的代码遵循所有规则,编译器就有义务生成具有与语言定义和“抽象机器”完全匹配的行为的可执行文件.但是如果你破坏了任何规则,特别是如果你的代码徘徊在任何未定义的行为中,所有的赌注都会关闭,合同都是无效的,编译器基本上可以做任何想做的事情.

例如,如果你写

int i = 1;
printf("%d\n",i++ + i++);    /* WRONG */

当您更改优化级别时,您很可能会发现表达式的值会发生变化.

(不用说,故事的寓意不是,“如果你编写未定义的代码,你必须要小心你使用的优化设置.”正确的教训是,“不要编写依赖于的代码未定义的行为.“)

相关文章

本程序的编译和运行环境如下(如果有运行方面的问题欢迎在评...
水了一学期的院选修,万万没想到期末考试还有比较硬核的编程...
补充一下,先前文章末尾给出的下载链接的完整代码含有部分C&...
思路如标题所说采用模N取余法,难点是这个除法过程如何实现。...
本篇博客有更新!!!更新后效果图如下: 文章末尾的完整代码...
刚开始学习模块化程序设计时,估计大家都被形参和实参搞迷糊...