是否每次都读取数组值作为循环停止条件?

时间:2015-08-01 22:27:09

标签: c loops for-loop memory

示例:

for (int i = 0; i < a[index]; i++) {
      // do stuff
}

每次都会a[index]阅读吗?如果不是,如果有人想要更改循环中a[index]的值,该怎么办?我自己从未见过它,但编译器是否做出了这样的假设?

如果条件是i < val-2,那么每次都会评估吗?

3 个答案:

答案 0 :(得分:3)

当系统不受程序其他部分的影响时,编译器将正常执行优化。因此,如果在条件参数的for循环内进行更改,编译器将不会进行优化。

如上所述,编译器应该读取数组并在代码片段中的每次迭代之前检查它。您可以按如下方式优化代码,然后它只会读取数组一次以进行循环条件检查。

int cond = a[index];
for (int i = 0; i < cond; i++) {
      // do stuff
}

答案 1 :(得分:2)

好吧,也许吧。

符合标准的编译器将生成与其相似的代码 每次都读。

如果manage.py migrate和/或index属于存储类array,则每次都会对其进行重新评估。

如果不是,并且循环内容没有以可以预期修改其值的方式使用它们,则优化器可能会决定使用缓存结果。

答案 2 :(得分:1)

Co不会将表达式的结果存储在临时变量中。因此,所有表达式都在原地进行了评估。请注意,任何for循环都可以更改为while循环:

for ( def_or_expr1 ; expr2 ; expr3 ) {
    ...
}

变为:

def_or_expr1;
while ( expr2 ) {
    ...
cont:
    expr3;
}
{p> continue循环中的更新: for与上面的while循环中的goto cont;相同。即expr3会针对每次迭代进行评估。

编译器可以基本上应用任何可以证明不会改变程序本质的优化。描述完整的细节对此来说太过分了,但总的来说,它可以(并且将会)优化:

  • a[index]在循环中没有改变:在循环之前读取一次并保持在临时(例如寄存器)。
  • 循环中更改了
  • a[index]:使用新值更新temp(register),避免内存访问(以及索引计算)。

为此,编译器必须假定在可见控制流之外不更改数组。这通常是正在编译的文件(包含所有包含的文件)。对于使用链接时间优化(LTO)的现代系统,这可以是整个最终程序 - 减去动态库。

请注意,这是一个非常简短的描述。实际上,C standard非常清楚地定义了程序必须如何执行,因此编译器可以优化的方式和方式。

如果更改了数组,例如中断处理程序或其他线程,则事情会变得复杂。根据您的目标,您需要从volatile,原子操作(stdatomic.h,从C11开始)到线程锁/互斥/ semapores /等。控制对共享资源的访问。