【问题标题】:Does c optimize the check portion of for loops?c 是否优化了 for 循环的检查部分?
【发布时间】:2018-02-28 20:33:13
【问题描述】:

使用下面的代码,min 函数实际会被调用多少次

for (int i = 0; i < min(size, max_size); i++) {
   //Do something cool that does not involve changing the value of size or max size
}

编译器会注意到他们可以计算最小值并注册它,还是我应该在进入循环之前显式创建一个变量来保存该值?什么样的语言能够对此进行优化?

作为一个扩展,如果我在一个类似循环的面向对象语言中,除了看起来更像这样

for (int i = 0; i < object.coolFunc(); i++) {
   //Code that may change parameters and state of object but does not change the return value of coolFunc()
}

什么会被优化?

【问题讨论】:

  • 这取决于编译器和标志。可能会被优化,也可能不会。
  • 这取决于特定的编译器。但是传统的很可能会对此进行优化。
  • 试试godbolt.org。它向您展示了各种编译器生成的程序集。
  • 我不会依赖它来优化。一方面有很多因素会影响它,而且很容易强制编译器在另一方面只调用一次。
  • @EugeneSh。使用像 gcc 这样的优秀编译器进行优化非常棒,但假设您正在为 MCU 编码,芯片制造商提供的一些交叉编译器充其量只是不稳定。尽管对 SO 的普遍看法是编译器比我好,但我被教导不要编写懒惰的代码,也不要让编译器为我完成工作。如果循环条件显然可以在循环之前完成,那就不费吹灰之力了。

标签: c++ c optimization


【解决方案1】:

只要启用了优化,任何好的编译器都会通过对其中的明显不变的子表达式进行一次评估来优化for 循环的控制表达式。这里,“不变”意味着子表达式的值在循环执行时不会改变。 “可见”意味着编译器可以看到表达式是不变的。有些事情会干扰这一点:

  • 假设在循环中调用了某个函数,并将size 的地址作为参数传递。由于该函数的地址为size,它可以改变size 的内容。也许函数没有这样做,但编译器可能无法看到函数的内容。它的源代码可能在另一个文件中。或者函数可能非常复杂,编译器无法对其进行分析。那么编译器看不到size没有变化。

  • min 不是标准的 C 函数,因此您的程序必须在某个地方定义它。如上所述,如果编译器不知道 min 做了什么,或者编译器分析起来过于复杂(在这种特殊情况下不太可能,但通常情况下),编译器可能无法看到它是pure function.

当然,C 标准不保证这种优化。但是,随着您在编程方面变得有经验,您对编译器和其他工具的知识应该会增长,并且您将熟悉对好的工具的期望,并且您还将学会提防上述问题。对于简单的表达式,您可以期望编译器进行优化。但是您需要对可能干扰优化的事情保持警惕。

【讨论】:

  • 对于"invariant",没有变化的值是不够的。正如您在下面提到的纯函数概念一样,子表达式应该没有副作用,或者只有在子表达式在循环内部和循环外部时具有等效的副作用。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-12-23
  • 1970-01-01
  • 2020-11-19
  • 2013-02-19
  • 2011-07-04
  • 2010-11-15
  • 2014-09-28
相关资源
最近更新 更多